2010-12-31 9 views
11

me tienen dicho código que funciona bien:¿Por qué el código que usa la estructura local como parámetro para la función STL no se compila en 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; 
} 

Pero si lo cambio a este estilo:

#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; 
} 

No compilará, diciendo:

error: no matching function for call to ‘transform(char [11], char*, char [11], main()::F)’

¿Qué pasa?

La versión de gcc es 4.4, que no reconoce expresiones lambda.

+0

¿Está recopilando como C++ 03 o C++ 0x? –

Respuesta

10

En C++ - 98/03 el segundo código no es válido, ya que F es un tipo local; en los hechos, en §14.3.1.2 se declaró que

A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.

[Example:

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] [Note: a template type argument may be an incomplete type (3.9). ]

En C++ - 0x esta limitación se elimina; en la misma sección, el nuevo proyecto de norma (N3126) muestra explícitamente en el ejemplo:

[ Example:

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 
} 

— end example ] [ Note: a template type argument may be an incomplete type (3.9). — end note ]

+1

Estamos en C++ 03 o C++ 0x, ya no en C++ 98. Por supuesto, el punto sigue siendo válido, pero citar de un Estándar obsoleto no tiene sentido. – Puppy

+0

@DeadMG: desafortunadamente no pude encontrar un borrador libre de C++ 03, así que me tengo que quedar con C++ 98 para las citas ': ('; aún así, verifiqué la lista no oficial de cambios y el §14.3 no es incluido en los cambios, por lo que la cita debe seguir siendo válida para C++ 03. –

+0

Ya veo ... ¿sabes por qué se produjo tal limitación? – RnMss

4

g ++ 4.5.1 compiles your code (con -std=c++0x opción).

Su segundo ejemplo de código está mal formada en C++ 03 pero válida en C++ 0x

std::transform es

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

Sin embargo g ++ 4.4 doesn't support local types as template arguments (incluso con - std=c++0x opción ] para que obtenga un error.

1: Un tipo local, un tipo sin enlace, un tipo sin nombre o un tipo compuesto de cualquiera de estos tipos no ser utilizado como una plantilla-argumento para una plantilla tipo-parámetro. (ISO C++ 03 §14.3.1.2)

+0

No sabía el parámetro "-std = C++ 0x", gracias. – RnMss

Cuestiones relacionadas