2009-10-20 3 views
9

Voici quelque chose que j'ai observé à travers différents compilateurs. Il semble qu'il y ait des bogues de compilateur.Pourquoi la gestion d'expression de paramètre de modèle non-type est-elle incohérente entre les compilateurs?

template <int I> 
struct X 
{ }; 

int main(void) 
{ 
    X<(16 > 1)> a;  // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 
    X<(int(16) > 1)> b; // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 
    X<(16 >> 1)> c;  // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 
    X<(int(16) >> 1)> d; // Fails on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 

    X<16 > 1> e;   // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1 
    X<int(16) > 1> f; // Fails on vc9, fails on g++ 4.1.2, fails on Comeau 4.3.10.1 
    X<16 >> 1> g;  // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1 
    X<int(16) >> 1> h; // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1 
} 

Pourquoi cette incohérence? Qu'est-ce qui est autorisé/refusé par la norme? Un tel comportement est également responsable de l'erreur de syntaxe lors de l'utilisation de BOOST_AUTO sur vc9. Il me semble que Comeau fait le bon travail en rejetant toutes les expressions sans parenthèses.

+5

Je ne pense pas que cela n'a rien à voir avec le modèle étant non type, mais plutôt parce qu'il utilise le caractère '>' à l'intérieur du modèle. – Marcin

+0

Vous avez raison Marcin, j'ai vu ce comportement incohérent avec les opérateurs '>' et '>>' surchargés de classes définies par l'utilisateur. – Sumant

+2

Parce que ce serait une construction rarement utilisée et donc moins susceptible d'être testé. Et vous seriez fâché de les utiliser en code réel de toute façon. Mais cela vaut la peine de les soumettre comme tests au fabricant du compilateur afin qu'ils puissent l'ajouter à leur suite de tests de choses folles que les gens font. –

Répondre

8

Les règles sont les suivantes pour C++ 03:

Après la recherche de nom (3.4) trouve qu'un nom est un modèle nom, si ce nom est suivi d'un <, le < est toujours pris comme le début d'une liste template-argument-list et jamais comme un nom suivi par l'opérateur less-than. Lors de l'analyse d'un ID de modèle, le premier > non imbriqué [foot-note: A > qui contient l'ID de type d'un dynamic_cast, static_cast, ou const_cast, ou qui contient les arguments de modèle d'un ID de modèle suivant, est considéré comme imbriqué aux fins de cette description. ] est considéré comme la fin de la liste template-argument-list plutôt que comme un opérateur supérieur à.

Le résultat est donc:

X<(16 > 1)> a;  // works 
    X<(int(16) > 1)> b; // works 
    X<(16 >> 1)> c;  // works 
    X<(int(16) >> 1)> d; // works 

    X<16 > 1> e;   // fails 
    X<int(16) > 1> f; // fails 
    X<16 >> 1> g;  // works (">>" is not a ">" token) 
    X<int(16) >> 1> h; // works (">>" is not a ">" token). 

Cependant, en C++ 0x les éléments suivants sont les règles

Après fi nom de recherche (3.4) PDN qu'un nom est un template- name, ou que operator-function-id fait référence à un ensemble de fonctions surchargées dont tout membre est un modèle de fonction, s'il est suivi d'un <, le < est toujours considéré comme le délimiteur d'une liste template-argument-list et jamais comme le moins que l'opéra ou. Lors de l'analyse d'une liste template-argument, la première [> note non-imbriquée: A > qui contient l'identificateur de type d'un dynamic_cast, static_cast, ou const_cast, ou qui contient les arguments de modèle d'un modèle suivant. id, est considéré comme imbriqué dans le cadre de cette description.] est considéré comme le délimiteur de fin plutôt qu'un opérateur supérieur à. De même, le premier >> non imbriqué est traité comme deux jetons > consécutifs mais distincts, dont le premier est considéré comme la fin de la liste template-argument-list et complète l'ID du template.

Résultat sera

X<(16 > 1)> a;  // works 
    X<(int(16) > 1)> b; // works 
    X<(16 >> 1)> c;  // works 
    X<(int(16) >> 1)> d; // works 

    X<16 > 1> e;   // fails 
    X<int(16) > 1> f; // fails 
    X<16 >> 1> g;  // fails (">>" translated to "> >") 
    X<int(16) >> 1> h; // fails (">>" translated to "> >") 

Assurez-vous de désactiver le mode C++ 0x dans comeau lors du test

+0

Bonne réponse! Sur Comeau, avec C++ 0x désactivé, le résultat est comme décrit ci-dessus (6 travail, 2 échouent). – Sumant

+0

Vous pouvez toujours compter sur litb pour faire la recherche aussi :) – Marcin

2

Selon le Stroustrup: "Le premier non-imbriqué> termine une liste d'arguments modèle Si un plus grand que nécessaire est nécessaire, les parenthèses doivent être utilisées."

Ainsi, les compilateurs qui tolèrent le deuxième ensemble d'expressions le font de façon incorrecte; le compilateur qui échoue sur X<(int(16) >> 1)> d; est buggé.

+1

cela signifierait que les compilateurs qui échouent sur X <16 >> 1> sont également buggés, car >> n'est pas deux> (nuisance de template imbriquée célèbre) – falstro

Questions connexes