2010-08-03 7 views
5

J'essaie de pouvoir écrire une grammaire extensible en utilisant des fonctions, mais je n'arrive pas à trouver la bonne syntaxe pour accepter une fonction gabarit. J'utilise Visual C++ 2008. Il acceptera une variable du même type que la fonction template, ou une fonction non-template similaire, mais pas la fonction template elle-même.Opérateur de surcharge << pour accepter une fonction de gabarit

erreur 1 Erreur C2679: binaire '< <': aucun opérateur trouvé qui prend un opérande de droite de type 'fonction surchargée' (ou il n'y a pas de conversion acceptable) (ligne ***)

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>; // *** 

Quel est le type de Expression<int> si ce n'est pas le type de p ci-dessus? Comment est son type différent du type de ExpressionInt.

+0

FWIW, cette compile avec g ++ 4.4.1 –

Répondre

3

Votre code semble OK pour moi, et g ++ est très bien avec cela aussi. Cela semble être bug de résolution de surcharge bizarre dans Visual Studio. VS2005 semble avoir le même problème. Une solution possible est (testé avec 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

Modifier ceci:

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

à ceci:

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

'grammaire() << expression ()' a un sens complètement différent. –

+0

ah! ... mon mauvais .. je n'ai pas remarqué cette partie. Mais la façon dont il a surchargé l '«opérateur» était erronée, IMO. Je vais changer ça maintenant. –

+0

@Luther Je suis désolé .. mais wat est la signification complètement différente de 'Expression ();' à nouveau? C'est une fonction-modèle et la fonction devrait être appelée comme une fonction. N'est-ce pas? Je l'ai élaboré dans Visual Studio 2008 et il le compile! –

0

Comme autre solution, j'ai pu l'obtenir pour travailler sur VS2010 par coulée. J'ai utilisé le typedef pour plus de commodité. VS2008 fonctionnera probablement la même chose.

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 contient toujours le même bogue, mais au moins maintenant vous pouvez utiliser la plus récente 11 C++ alias la syntaxe du modèle si vous allez avec la solution de coulée:

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

font ensuite le casting comme ceci:

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