Почему код, использующий локальную структуру как параметр для функции 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;
}
Он не будет компилироваться, говоря:
error: нет соответствующей функции для вызова 'transform (char [11], char *, char [11], main():: F)
Что не так?
Версия gcc - 4.4, которая не распознает лямбда-выражения.
Ответы
Ответ 1
В С++ - 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). ]
В С++ - 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). - конечная нота]
Ответ 2
g++ 4.5.1 компилирует ваш код (с опцией -std=c++0x
).
Второй образец кода плохо сформирован в С++ 03 1 но действителен в С++ 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 С++ 03 §14.3.1.2)