Ambiguïté des modèles C ++

Un ami et moi discutions de modèles C ++. Il m’a demandé ce que cela devrait faire:

#include  template  struct A { A(bool) { std::cout << "bool\n"; } A(void*) { std::cout << "void*\n"; } }; int main() { A *d = 0; const int b = 2; const int c = 1; new A (c) > (d); } 

La dernière ligne principale contient deux parsings syntaxiques raisonnables. Est-ce que ‘b’ est l’argument de modèle ou est-ce que b > (c) l’argument de modèle?

Même s’il est sortingvial de comstackr cela et de voir ce que nous obtenons, nous nous demandions ce qui permettait de lever l’ambiguïté.

Autant que je sache, il serait compilé en tant que new A(c) > d . C’est le seul moyen raisonnable de l’parsingr à mon humble avis. Si l’parsingur ne peut pas supposer, dans des circonstances normales,> mettre fin à un argument de modèle, cela créerait beaucoup plus d’ambiguïté. Si vous voulez le contraire, vous devriez avoir écrit:

 new A<(b > c)>(d); 

Comme indiqué par Leon & Lee, 14.2 / 3 (C ++ ’03) définit explicitement ce comportement.

C ++ ‘0x ajoute au plaisir avec une règle similaire s’appliquant à >> . Le concept de base est que, lors de l’parsing d’une liste d’arguments-modèles, un >> non nested sera traité comme deux >> jetons distincts et non comme l’opérateur de décalage de droite:

 template  struct A { A(bool); A(void*); }; template  class C { public: C (int); }; int main() { A *d = 0; const int b = 2; const int c = 1; new C > (c) > (d); // #1 new C  > (c) > (d); // #2 } 

‘# 1’ et ‘# 2’ sont équivalents dans ce qui précède.

Cela corrige bien sûr la gêne de devoir append des espaces dans les spécialisations nestedes:

 C> c; // Parse error in C++ '98, '03 due to "right shift operator" 

La norme C ++ définit que si, pour un nom de modèle suivi d’un < , le < est toujours le début de la liste d'arguments de modèles et que le premier > non nested est considéré comme la fin de la liste d'arguments de modèles.

Si vous souhaitez que le résultat de l'opérateur > soit l'argument de modèle, vous devez inclure l'expression entre parenthèses. Vous n'avez pas besoin de parenthèses si l'argument fait partie d'une static_cast<> ou d'un autre modèle.

La gourmandise du lexer est probablement le facteur déterminant en l’absence de parenthèses pour le rendre explicite. Je suppose que le lexer n’est pas gourmand.