39 votes

Opérateur conditionnel du type de retour et deux en phase de recherche

Considérons le fragment de code suivant:

struct Base { };
struct Derived : Base { };

void f(Base &) { std::cout << "f(Base&)\n"; }

template <class T = int>
void g() {
    Derived d;
    f(T{} ? d : d); // 1
}

void f(Derived &) { std::cout << "f(Derived&)\n"; }

int main() {
    g();
}

Dans ce cas, je pense que l'appel à la fonction f à // 1 doit être recherché dans la première phase, depuis son argument est de type unambigously Derived&, et ainsi être résolus en f(Base&) qui est le seul de la portée.

Clang 3.8.0 est d'accord avec moi, mais GCC 6.1.0 n'est pas, et reporte la recherche d' f jusqu'à la phase deux, où l' f(Derived&) est ramassé.

Le compilateur est de droite ?

23voto

Loki Astari Points 116129

À l'aide de la dernière version de la norme C++ Actuellement n4582.

Dans la section 14.6 (p10), il est dit que le nom est lié au point de la déclaration si le nom n'est pas dépendant d'un paramètre du modèle. Si elle dépend d'un paramètre de modèle cela est défini dans la section 14.6.2.

Section 14.6.2.2 revient à dire que l'expression est dépendante du type si toute sous-expression est dépendante du type.

Maintenant, depuis l'appel à l' f() dépend de son paramètre. Vous regardez le type de paramètre pour voir si c'est selon le type. Le paramètre False<T>::value ? d : d. Ici, la première condition est fonction du type T.

Par conséquent, nous concluons que l'appel est lié au moment de l'instanciation pas de déclaration. Et, par conséquent, doit se lier à: void f(Derived &) { std::cout << "f(Derived&)\n"; }

Donc g++ a le plus précis de mise en œuvre.

14.6 la résolution de Nom [temp.res]

Par 10:

Si un nom ne dépend pas d'un modèle à paramètre (tel que défini dans 14.6.2), une déclaration (ou d'un ensemble de déclarations) pour que le nom doit être portée au point où le nom apparaît dans la définition de modèle; le nom est lié à la déclaration (ou déclarations) trouvé à ce point, et cette liaison n'est pas affecté par des déclarations qui sont visibles au moment de l'instanciation.

14.6.2.2 en fonction du Type d'expressions [temp.dep.expr]

Sauf comme il est décrit ci-dessous, une expression est dépendant du type si toute sous-expression est dépendant du type.

7voto

Synxis Points 5585

Je pense que gcc (et visual studio, par la voie) sont à droite sur celle-ci.

n4582, §14.6.2.2

Sauf comme il est décrit ci-dessous, une expression est dépendant du type si toute sous-expression est dépendant du type.

En T{} ? d : d, il y a 3 sous-expressions:

  • T{}, évidemment dépendante du type
  • d (2 fois), pas dépendante du type

Depuis il est dépendante du type de sous-expression et l'opérateur ternaire ne figure pas dans la liste des exceptions prévues à l'article 14.6.2.2, elle est considérée comme dépendante de type.

1voto

user1810087 Points 1384

Selon c++ projet (n4582) §14.7.1.5:

À moins qu'un modèle de fonction de la spécialisation a été explicitement instancié ou explicitement spécialisé, le modèle de fonction la spécialisation est implicitement instancié lors de la spécialisation est référencé dans un contexte qui nécessite la définition d'une fonction d'exister. À moins qu'un appel à une fonction de modèle explicite de la spécialisation ou de une fonction membre d'une explicitement classe spécialisée, un modèle d' l'argument par défaut pour un modèle de fonction ou une fonction de membre d'un modèle de classe est automatiquement instanciés lorsque la fonction est appelée dans un contexte qui exige que la valeur de l'argument par défaut.

Je dirais que gcc est plus correcte à ce sujet.

Par exemple si vous créez une version spécialisée d' void g() vous obtenez à la fois compilateur de faire de même.

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