43 votes

Spécialisation de modèle de classe, classement partiel et synthèse de fonctions

Les règles pour la cueillette de la classe template de la spécialisation est préférable d'impliquer la réécriture de l'spécialisations en fonction des modèles et de détermination du modèle de fonction est de plus en plus spécialisée par les règles d'ordonnancement pour les modèles de fonction [temp.classe.la commande]. Considérons cet exemple, puis:

#include <iostream>

template <class T> struct voider { using type = void; };
template <class T> using void_t = typename voider<T>::type;

template <class T, class U> struct A { };

template <class T> int foo(A<T, void_t<T>> ) { return 1; }
template <class T> int foo(A<T*, void> )     { return 2; }

int main() {
    std::cout << foo(A<int*, void>{});
}

Gcc et clang imprimer 2 ici. Cela fait sens avec certains exemples précédents - en déduire à l'encontre d'un non déduit du contexte (void contre void_t<T>) est tout simplement ignorés, donc en déduire <T, void_t<T>> contre <X*, void> réussit, mais en déduire <T*, void> contre <Y, void_t<Y>> d'échec dans les deux arguments. Des beaux.

Considérons maintenant cette généralisation:

#include <iostream>

template <class T> struct voider { using type = void; };
template <class T> using void_t = typename voider<T>::type;

template <int I> struct int_ { static constexpr int value = I; };

template <class T, class U> struct A      : int_<0> { };
template <class T> struct A<T, void_t<T>> : int_<1> { };
template <class T> struct A<T*, void>     : int_<2> { };

int main() {
    std::cout << A<int*, void>::value << '\n';
}

Les deux clang et gcc rapport de cette spécialisation comme ambiguë, entre 1 et 2. Mais pourquoi? La synthèse des modèles de fonction ne sont pas ambigus. Quelle est la différence entre ces deux cas?

5voto

Richard Smith Points 3935

Clang est GCC-compatible (et compatible avec les code qui dépend à la fois de ces comportements).

Considérer [temp.déduire.type]p1:

[...] une tentative est faite pour trouver le modèle des valeurs d'argument (un type pour un type de paramètre, une valeur pour un non-type d'un paramètre ou d'un modèle à un paramètre de modèle) de P, après substitution de la déduite des valeurs (appel il la déduit Un), compatible avec A.

Le nœud de la question est ce que "compatible" signifie ici.

Quand partiellement la commande de modèles de fonction, Clang simplement déduit, dans les deux sens; si la déduction réussit dans un sens mais pas dans l'autre, il suppose que cela signifie que le résultat sera "compatible", et l'utilise comme le résultat de la commande.

Quand partiellement la commande de modèle de classe partielle spécialisations, cependant, Clang interprète "compatible" le sens de "même". Par conséquent, il ne considère que l'une spécialisation partielle à être plus spécialisé que l'autre, si la substitution de la déduire des arguments de l'un d'eux dans l'autre de reproduire l'original partielle de la spécialisation.

Modification de l'une de ces deux pour correspondre à l'autre des pauses importantes quantités de code réel. :(

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