2010-08-03 18 views
5

Sto cercando di essere in grado di scrivere una grammatica estensibile usando le funzioni, ma non riesco a trovare la sintassi corretta per accettare una funzione template. Sto usando Visual C++ 2008. Accetterà una variabile dello stesso tipo della funzione template, o una funzione non-template simile, ma non la funzione template stessa.Operatore di overloading << per accettare una funzione template

errore 1 Errore C2679: binario '< <': nessun operatore trovato che prende un operando a destra di tipo 'sovraccarico-funzione' (o non v'è alcuna conversione accettabile) (line ***)

class Grammar { 
    friend Grammar operator << (const Grammar& lhs, const char* rhs) { 
     return lhs; // append rhs to grammar 
    } 
    template<typename T> 
    friend Grammar operator << (const Grammar& lhs, T (*rhs)()) { 
     return lhs; // append rhs() to grammar 
    } 
}; 

template<typename T> 
class ExpressionParticle { 
}; 

template<typename T> 
ExpressionParticle<T> Expression() ; 

ExpressionParticle<int> ExpressionInt(); 

int _tmain (int argc, _TCHAR *argv[]) 
{ 
    ExpressionParticle<int> (*p)(); 

    p = Expression<int>; 

    Grammar() << "p"; 
    Grammar() << p; 
    Grammar() << ExpressionInt; 
    Grammar() << Expression<int>; // *** 

Qual è il tipo di Expression<int> se non è il tipo di p in sopra? Com'è il suo tipo diverso dal tipo di ExpressionInt.

+0

FWIW, questa compila con g ++ 4.4.1 –

risposta

3

il codice sia OK per me, e g ++ è bene con quello anche. Questo sembra essere uno strano bug di sovraccarico in Visual Studio. VS2005 sembra avere lo stesso problema. Una possibile soluzione è (testato con VS2005):

template<class T> 
T id(T t) {return t; } 
int main() 
{ 
    ExpressionParticle<int> (*p)(); 

    p = Expression<int>; 

    Grammar() << "p"; 
    Grammar() << p; 
    Grammar() << ExpressionInt; 
    Grammar() << id(Expression<int>); // *** 
} 
0

Modifica questo:

class Grammar { 
    friend Grammar operator << (const Grammar& lhs, const char* rhs) { 
     return lhs; // append rhs to grammar 
    } 
    template<typename T> 
    friend Grammar operator << (const Grammar& lhs, T (*rhs)()) { 
     return lhs; // append rhs() to grammar 
    } 
}; 

a questo:

class Grammar { 
public: 
    Grammar& operator << (const char* rhs) { 
     return *this; // append rhs to grammar 
    } 
    template<typename T> 
    Grammar& operator << (const T &rhs) { 
     return *this; // append rhs() to grammar 
    } 
}; 
+0

'Grammar() << Expression ();' ha un significato completamente diverso. –

+0

ah! ... mio male .. non ho notato quella parte di esso. Ma il modo in cui ha sovraccaricato l'operatore << 'era sbagliato, IMO. Lo cambierò ora. –

+0

@Luther Mi dispiace .. ma wat è il significato completamente diverso di 'Expression ();' di nuovo? È una funzione modello e la funzione dovrebbe essere chiamata come una funzione. Non è vero? L'ho elaborato in Visual Studio 2008 e lo compila! –

0

Come un'altra soluzione, sono stato in grado di farlo funzionare su VS2010 per fusione. Ho usato il typedef per comodità. VS2008 probabilmente funzionerà allo stesso modo.

int _tmain (int argc, _TCHAR *argv[]) 
{ 
    typedef ExpressionParticle<int> (*FCN)(); 

    ExpressionParticle<int> (*p)() = Expression<int>; 

    Grammar() << "p"; 
    Grammar() << p; 
    Grammar() << ExpressionInt; 
    Grammar() << static_cast<FCN>(Expression<int>); 
0

MSVC 2013 contiene ancora lo stesso problema, ma almeno ora è possibile utilizzare il C++ 11 alias sintassi del modello più recente se si va con la soluzione di casting:

template <typename T> 
using Fptr = ExpressionParticle<T>(*)(); 

Poi fare il cast in questo modo:

Grammar() << Fptr<int>(Expression<int>) << endl; 
Problemi correlati