44 votes

Spécialisation partielle des modèles variadiques

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

template <class ...Types>
struct X {};               // #1

template <class T1>
struct X<T1> {};           // #2

template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3

X<int> x;                  // #2 or #3 ?

Je soupçonne que X<int> est ambiguë. Il l'est parce que :

Il est évident que les numéros 2 et 3 sont plus spécialisés que le numéro 1, les numéros 2 et 3 sont maintenant comparés. Selon 14.5.5.2, considérons lequel des #2' et #3' suivants est le plus spécialisé.

template <class T1>
void f(X<T1>);             // #2'

template <class T1, class ...Types>
void f(X<T1, Types...>);   // #3'

Selon 14.8.2.4, la première étape est la déduction du modèle d'argument 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<A1>, le T1 déduit est A1, et Types est vide.

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

La deuxième étape est effectuée en utilisant le modèle #3' comme modèle d'argument et le modèle #2' comme modèle de paramètre. Étant donné que le seul type d'argument est X<A1, Args...>, selon 14.8.2.5/9 (notez que ce paragraphe a été récemment révisé par N3281), Args est simplement ignoré, le T1 déduit est A1 et la déduction d'argument réussit.

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

Enfin, les déductions d'arguments bidirectionnels ont réussi. Donc #2 est tout aussi spécialisé que #3. En conclusion, X<int> est ambiguë.

Ma question est la suivante : "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 <class ...T>
struct common_type;            // #1

template <class T>
struct common_type<T>          // #2
{
    typedef T type;
};

template <class T, class U>
struct common_type<T, U>       // #3
{
    typedef
        decltype(true ? declval<T>() : declval<U>())
    type;
};

template <class T, class U, class ...V>
struct common_type<T, U, V...> // #4
{
    typedef typename
        common_type<typename common_type<T, U>::type, V...>::type
    type;
};

Lorsque common_type<A, B> est utilisé, les points 3 et 4 sont ambigus.

Note : 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 changements de N3281.

1 votes

Il semble que vous ayez raison. Un paquet de paramètres vide ne devrait pas affecter l'ordre partiel. gcc semble ignorer cela et placer un modèle variadique plus bas dans la liste, toutes choses étant égales par ailleurs. Par exemple, il compile un exemple à 14.5.6.2/5 qui est explicitement déclaré comme étant ambigu.

0 votes

La correction est généralement le sujet des tests unitaires, surtout en programmation. Cela permet de s'assurer que votre interprétation est correcte et que vous comprenez les spécifications du langage avec un haut degré de confiance, deux éléments qui peuvent être remis en question ici.

0 votes

@n.m. est ce code de quoi parlez-vous ? J'ai pris ce code de N3242 comme indiqué dans le lien Wikipedia

8voto

Mikhail Semenov Points 309

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

Dans la plupart des cas, tous les paramètres du modèle doivent avoir des valeurs pour que la déduction soit réussie. pour que la déduction réussisse, mais à des fins d'ordonnancement partiel, un peut rester sans valeur, à condition qu'il ne soit pas utilisé dans l'élément types utilisés pour l'ordonnancement partiel. [Note : Un paramètre de modèle utilisé dans un contexte non instruit est considéré comme utilisé. -fin de la note] [ Exemple :

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

Dans votre cas, c'est le n°3 qui sera utilisé.

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