17 votes

Moulage de type constructeur dans les paramètres d'appel de fonction

Je ne comprends pas pourquoi le code suivant ne compile pas lorsqu'il utilise un casting de type constructeur :

template<typename T> void foo(const T& t){}

int main(){
  foo(unsigned char(0));
}

Les erreurs sont :

  • error: expected primary-expression before ‘unsigned’ pour gcc.
  • error: expected '(' for function-style cast or type construction pour clang

Cependant ces trois syntaxes sont correctes :

template<typename T> void foo(const T& t){}

int main(){
  // c-style cast
  foo((unsigned char)0);

  // without unsigned
  foo(char(0));

  // aliased unsigned char
  typedef unsigned char uchar;
  foo(uchar(0));
}

C'est donc l'espace dans la police qui est à blâmer ici.

J'ai pensé que ça pouvait être lié d'une manière ou d'une autre à notre vieil ami. l'analyse la plus contrariante J'ai donc essayé le syntaxe d'initialisation uniforme qui est censé se débarrasser de ce genre d'ambiguïtés, mais pas de chance :

template<typename T> void foo(const T& t){}

int main(){
  foo(unsigned char{0});
}

Mais quand même :

  • error: expected primary-expression before ‘unsigned’ pour gcc.
  • error: expected '(' for function-style cast or type construction pour clang

Ma question est donc la suivante : pourquoi n'est-il pas permis d'avoir un type contenant un espace dans les casts de style fonction ? Cela ne me semble pas ambigu.

note : Je sais que je peux écrire foo<unsigned char>(0) mais cela ne répond pas à la question ;)

15voto

Lightness Races in Orbit Points 122793

[C++11: 5.2.3/1]: A spécificateur de type simple (7.1.6.2) ou spécificateur de nom de type (14.6) suivi d'une parenthèse liste d'expressions construit une valeur du type spécifié à partir de la liste d'expressions. [..]

En examinant la grammaire, nous voyons que la seule façon d'obtenir unsigned char de la spécificateur de type simple c'est en concaténant deux d'entre eux.

Pour démentir la rumeur selon laquelle le tableau 10 affirme le contraire, que j'ai peut-être moi-même lancée il y a peu (:P), le titre du tableau indique "spécificateur(s)" (notez le pluriel facultatif), et renvoie au passage ci-dessous :

[C++11: 5.2.3/2]: [..] Le tableau 10 récapitule les combinaisons de spécificateurs de type simple et les types qu'ils spécifient. (c'est moi qui souligne)

Maintenant, en combinant spécificateurs de type simple est autorisé dans certains cas :

[C++11: 7.1.6.2/3]: Lorsque plusieurs spécificateurs de type simple sont autorisés, ils peuvent être librement mélangés avec d'autres Déclinaison des spécificateurs dans n'importe quel ordre. [..]

mais rien n'indique que ce soit le cas avec la notation fonctionnelle, qui indique clairement " a spécificateur de type simple " - singulier.

Par conséquent, GCC est correct, et Visual Studio est faux.

Quant à pourquoi c'est le cas... eh bien, je ne sais pas. Je pense que nous pourrions trouver un cas limite ambigu, mais Casey fait remarquer dans les commentaires ci-dessous que cette autorisation serait incompatible avec la syntaxe des appels de fonction, puisque les noms des fonctions ne peuvent pas contenir d'espaces.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X