Spécialisation partielle des modèles variadiques

Considérons le modèle de classe «X» suivant et ses spécialisations partielles.

template  struct X {}; // #1 template  struct X {}; // #2 template  struct X {}; // #3 X x; // #2 or #3 ? 

Je pense que X est ambigu. C’est parce que:

Il est évident que les deux # 2 et # 3 sont plus spécialisés que # 1, # 2 et # 3 sont maintenant comparés. D’après 14.5.5.2, considérons lesquels des # 2 ‘et # 3 suivants sont plus spécialisés.

 template  void f(X); // #2' template  void f(X); // #3' 

Selon 14.8.2.4, la première étape est la déduction des arguments de modèle en utilisant # 2 ‘comme modèle d’argument et # 3’ comme modèle de paramètre. Étant donné que le seul type d’argument est X , T1 déduit est A1 et Types est vide.

 A = X, P = X => T1 = A1, Types = {} 

La deuxième étape consiste à utiliser # 3 ‘comme modèle d’argument et # 2’ comme modèle de paramètre. Étant donné que le seul type d’argument est X , d’après 14.8.2.5/9 (notez que ce paragraphe a été récemment révisé par N3281), Args est simplement ignoré, T1 déduit et la déduction d’argument réussit.

 A = X, P = X => T1 = A1 (Args is ignored) 

Enfin, les déductions d’argument bidirectionnelles ont réussi. Donc, le n ° 2 est tout aussi spécialisé que le n ° 3. En conclusion, X est ambigu.

Ma question est: “mon interprétation est-elle correcte?”

Si cette interprétation est correcte, la définition de ‘std :: common_type’ dans 20.9.7.6/3 est inappropriée.

 template  struct common_type; // #1 template  struct common_type // #2 { typedef T type; }; template  struct common_type // #3 { typedef decltype(true ? declval() : declval()) type; }; template  struct common_type // #4 { typedef typename common_type<typename common_type::type, V...>::type type; }; 

Lorsque common_type est utilisé, # 3 et # 4 sont ambigus.

Remarque: sur le premier exemple, GCC 4.7.0 (snapshot) et Clang 3.0 sélectionnent # 2. Cependant, ces compilateurs sont si peu fiables qu’ils ne suivent pas les autres modifications de N3281.

14.8.2.4, section 11 (je me réfère au projet N3242).

Dans la plupart des cas, tous les parameters du modèle doivent avoir des valeurs pour que la déduction réussisse, mais pour des raisons de classement partiel, un paramètre de modèle peut restr sans valeur à condition qu’il ne soit pas utilisé dans les types utilisés pour le classement partiel. [Remarque: un paramètre de modèle utilisé dans un contexte non déduit est considéré comme utilisé. —End note] [Exemple:

 template  T f(int); // #1 template  T f(U); // #2 void g() { f(1); // calls #1 } 

Dans votre cas, # 3 sera utilisé.