2010-12-31 16 views
11

devo tale codice che funziona bene:Perché il codice che utilizza la struct locale come parametro per la funzione STL non viene compilato in 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; 
} 

Ma se si modifica a questo stile:

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

non si compila, dicendo:

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

Cosa c'è di sbagliato?

versione gcc è 4.4, che non riconosce le espressioni lambda.

+0

State compilazione come C++ 03 o C++ 0x? –

risposta

10

In C++ - 98/03 il secondo codice non è valido, poiché F è un tipo locale; infatti, a §14.3.1.2 è affermato che

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). ]

In C++ - 0x questa limitazione viene rimosso; nella stessa sezione, il nuovo progetto di norma (N3126) mostra in modo esplicito questo nell'esempio:

[ 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

Siamo in C++ 03 o C++ 0x, non più C++ 98. Naturalmente, il punto è ancora valido, ma il riferimento a uno standard obsoleto non ha senso. – Puppy

+0

@DeadMG: sfortunatamente non sono riuscito a trovare una bozza gratuita di C++ 03, quindi devo attenermi a C++ 98 per le citazioni ': ('; ancora, ho controllato la lista non ufficiale delle modifiche e §14.3 non è incluso nelle modifiche, quindi la quotazione dovrebbe essere ancora valida per C++ 03. –

+0

Vedo ... sai perché tale limitazione è avvenuta? – RnMss

4

g ++ 4.5.1 compiles your code (con l'opzione -std=c++0x).

tuo secondo esempio di codice è mal-formato in C++ 03 ma valido in C++ 0x

std::transform è

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

Tuttavia g ++ 4.4 doesn't support local types as template arguments (anche con opzione - std=c++0x ] in modo da ottenere un errore

1: un tipo locale, un tipo senza collegamento, un tipo senza nome o un tipo composto da uno di questi tipi non deve essere usato come argomento modello per un parametro di tipo template. (ISO C++ 03 §14.3.1.2)

+0

Non conoscevo il parametro "-std = C++ 0x", grazie. – RnMss

Problemi correlati