Il doit avoir des clauses template
distinctes pour chaque modèle concerné. Ici, deux modèles sont impliqués, que tous méritent leur (non vide) clauses de modèle:
- Le modèle de classe
Foo
- Le modèle constructeur
Considérons ce cas qui échoue à cause de l'ambiguïté comme à l'endroit où le paramètre U
appartient à
template<typename T>
struct A {
template<typename U> void f();
};
template<typename T, typename U>
void A<T>::f() { }
maintenant, ce qui est avec le paramètre U
? Bien sûr, le compilateur pourrait deviner qu'il pourrait appartenir à f
, mais deviner n'est pas ce que le compilateur aime :) La règle existante dit que selon l'imbrication des modèles, les clauses de modèles apparaissent dans le bon ordre. Tout est clair alors.
Même si l'on trouve une règle pour faire correspondre les paramètres aux arguments des modèles impliqués (pour l'instant je ne vois pas de difficulté réelle à le faire), cela serait incohérent. Parce qu'à partir de maintenant, une clause de modèle répertorie tous les paramètres que le modèle correspondant accepte. Tout comme une liste de paramètres de fonction. Si nous mettrions tout en une seule clause, que sémantique clair pourrait être cassé - pour ne pas mentionner que lorsque nous mettons la définition dans la classe à nouveau, tout d'un coup le modèle obtiendrait sa propre clause:
// provides arguments for A's parameters, then for f ones
// when it's called
A<int> a;
a.f<bool>();
Il est beaucoup plus naturel quand nous avons des clauses de template séparées qui attrapent chacune leurs propres arguments.Ainsi, la syntaxe pour la définition erronée ci-dessus est
template<typename T>
template<typename U>
void A<T>::f() { }
Maintenant, aussi le lecteur du code voit immédiatement que c'est une définition d'un modèle de membre, et non un second (potentiel accidentellement déclaré mais non utilisé) paramètre pour A
.
Ceci n'est pas un constructeur de copie. Le compilateur se plaindra si vous essayez de transmettre la classe 'Foo' par valeur. –