Question
Un ami et moi discutions de modèles C++.Il m'a demandé ce qu'il doit faire:
#include <iostream>
template <bool>
struct A {
A(bool) { std::cout << "bool\n"; }
A(void*) { std::cout << "void*\n"; }
};
int main() {
A<true> *d = 0;
const int b = 2;
const int c = 1;
new A< b > (c) > (d);
}
La dernière ligne principale dispose de deux raisonnable analyse.Est 'b' l'argument de modèle ou est b > (c)
l'argument de modèle?
Bien que, il est trivial de le compiler, et voyons ce que nous obtenons, nous nous demandions ce qui résout l'ambiguïté?
La solution
Autant que je sache, il serait compilé comme new A<b>(c) > d
.C'est la seule façon raisonnable de l'analyser à mon humble avis.Si l'analyseur ne peut pas assumer en vertu des circonstances normales, une > à la fin d'un argument de modèle, le résultat serait beaucoup plus d'ambiguïté.Si vous voulez de l'autre façon, vous devriez avoir écrit:
new A<(b > c)>(d);
Autres conseils
Comme l'a déclaré 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, c'est que lors de l'analyse d'un modèle de la liste d'arguments non imbriquées >>
seront traités comme deux distincts >
>
jetons et pas le décalage à droite de l'opérateur:
template <bool>
struct A {
A(bool);
A(void*);
};
template <typename T>
class C
{
public:
C (int);
};
int main() {
A<true> *d = 0;
const int b = 2;
const int c = 1;
new C <A< b >> (c) > (d); // #1
new C <A< b > > (c) > (d); // #2
}
'#1 et#2 " sont l'équivalent dans le ci-dessus.
Bien sûr, cela résout que la gêne d'avoir à ajouter des espaces imbriqués spécialisations:
C<A<false>> c; // Parse error in C++ '98, '03 due to "right shift operator"
Le standard C++ définit que si, pour un nom de modèle suivi par un <
, le <
est toujours le début de l'argument de modèle de liste et le premier non-imbriquées >
est considéré comme la fin du modèle de la liste d'arguments.
Si vous avez prévu que le résultat de l' >
exploitant l'argument de modèle, alors vous devrez mettre l'expression entre parenthèses.Vous n'avez pas besoin de parenthèses si l'argument a été le cadre d'un static_cast<>
ou un autre modèle d'expression.
La gourmandise de l'analyseur lexical est probablement le facteur déterminant en l'absence de parenthèses pour le rendre explicite.Je suppose que l'analyseur lexical n'est pas gourmand.