问题 为什么使用local struct作为STL函数参数的代码不能用g ++编译?


我有这样的代码,效果很好:

#include <algorithm>
#include <iostream>

char x[11]= "ABCDEFGHIJ";
char y[11];

struct F {
    char operator () (char c) const 
    { return c+1; }
};

int main()
{
    std::transform(x, x+10, y, F());
    y[10] = 0; std::cout <<y <<std::endl;
}

但如果我把它改成这种风格:

#include <algorithm>
#include <iostream>

char x[11]= "ABCDEFGHIJ";
char y[11];

int main()
{
    struct F {
        char operator () (char c) const 
        { return c+1; }
    };
    std::transform(x, x+10, y, F());
    y[10] = 0; std::cout <<y <<std::endl;
}

它不会编译,说:

错误:没有匹配函数来调用'transform(char [11],char *,char [11],main():: F)'

怎么了?

gcc版本是4.4,它不识别lambda表达式。


5138
2017-12-31 11:53


起源

你编译为C ++ 03还是C ++ 0x? - Martin York


答案:


在C ++ - 98/03中,第二个代码无效,因为F是本地类型;事实上,在§14.3.1.2中说明了这一点

本地类型,没有链接的类型,未命名的类型或从这些类型中的任何类型复合的类型不应用作模板类型参数的模板参数。

[例:

template <class T> class X { /* ... */ };
void f()
{
    struct S { /* ... */ };
    X<S> x3;         // error: local type used as template-argument
    X<S*> x4;        // error: pointer to local type used as template-argument
}

-end example] [注意:模板类型参数可能是不完整类型(3.9)。 ]

在C ++ - 0x中,此限制被删除;在同一部分中,新标准草案(N3126)在示例中明确显示:

[例如:

template <class T> class X { };
template <class T> void f(T t) { }
struct { } unnamed_obj;

void f() {
    struct A { };
    enum { e1 };
    typedef struct { } B;
    B b;
    X<A> x1;             // OK
    X<A*> x2;            // OK
    X<B> x3;             // OK
    f(e1);               // OK
    f(unnamed_obj);      // OK
    f(b);                // OK
}

- 结束示例] [注意:模板类型参数可能是不完整类型(3.9)。 - 结束说明]


10
2017-12-31 12:01



我们在C ++ 03或C ++ 0x,而不是C ++ 98。当然,这一点仍然有效,但引用过时的标准是毫无意义的。 - Puppy
@DeadMG:遗憾的是我找不到C ++ 03的免费草稿,所以我必须坚持使用C ++ 98作为报价 :( ;仍然,我检查了非官方的更改列表,§14.3未包含在更改中,因此引用应该对C ++ 03仍然有效。 - Matteo Italia
我明白了......你知道为什么会出现这种限制吗? - RnMss
没有C ++ 03这样的东西。目前只有一个C ++标准存在(C ++ 98,如果你愿意的话)。实际上更像C ++ 11的C ++ 0x很快就会成为一个标准,但它还没有。 - Yttrill
@Yttrill嗯,我也这么认为。但是抬头看来,似乎C ++ 03实际上并不是TC,而是C ++的全新版本。这似乎与GCC和Clang相矛盾,它只有-std = c ++ 98并且说“1998 ISO C ++标准加上修正。与C ++代码相同的-ansi”。奇怪的! - Johannes Schaub - litb


g ++ 4.5.1 编译你的代码 (与 -std=c++0x 选项)。

您的第二个代码示例在C ++ 03中格式不正确1 但在C ++ 0x中有效

std::transform 是

template < class InputIterator, class OutputIterator, class UnaryOperator >
  OutputIterator transform ( InputIterator first1, InputIterator last1,
                             OutputIterator result, UnaryOperator op );

但是g ++ 4.4 不支持本地类型作为模板参数 (即使 -std=c++0x 选项]所以你得到一个错误。

1:本地类型,没有链接的类型,未命名的类型或从这些类型中的任何类型复合的类型不应该用作模板类型参数的模板参数。 (ISO C ++03§14.3.1.2) 


4
2017-12-31 11:55



我不知道“-std = c ++ 0x”param,谢谢。 - RnMss