33 votes

Différences de résolution d'appels de modèles GCC et Clang

Étant donné le code suivant:

#include <iostream>

struct Alice
{
  template <typename A>
  void operator|(const A& /*a*/) const
  {
    std::cout << "operator| member" << std::endl;
  }
};

template <typename A>
void operator|(const A& /*a*/, const Alice& /*alice*/)
{
  std::cout << "operator| non-member" << std::endl;
}

int main()
{
  Alice a;
  Alice b;

  a | b;

  return 0;
}

Il se compile sans warning avec GCC 4.8.1, 4.9 et clang 3.4, mais donne des résultats différents.

$ g++ -Wall -Wextra -std=c++11 alice.cpp && ./a.out
operator| non-member

$ clang++ -Wall -Wextra -std=c++11 alice.cpp && ./a.out
operator| member

Quelles sont les causes de cette différence? Comment puis-je forcer le même comportement?

EDIT: fait Intéressant: la suppression de l' const qualifier à partir de la fonction de membre de fait de gcc préfèrent la fonction de membre également. Elle ne résout pas le problème, cependant.

EDIT: clang++ préfère les non-membres au lieu de cela, si -std=c++11 n'est pas spécifié.

EDIT: ICC 14.0 préfère la non-membre, pas d'avertissement émis.

8voto

Columbo Points 11661

Juste pour expliquer ce que la sortie correcte serait: en Raison de la résolution de surcharge, il y a deux viable fonctions: tout d'Abord, la spécialisation de la global operator|-modèle avec déduite des arguments, et bien sûr la spécialisation des membres de l'opérateur modèle de fonction. Les deux ont la même signature - la fonction de membre de modèle implicite de paramètre de l'objet de type Alice const& (voir §13.3.1/4).

Donc, à la fois viable fonctions (après l'argument de la déduction) ont la même signature. Et ni les modèles à partir de laquelle ils ont été instancié est plus spécialisé que les autres. C'est donc une ambiguïté et, par conséquent, mal formé, selon le §13.3.3.1. Étonnamment, VC++ est correcte!*

Comment puis-je forcer le même comportement?

Peut-être vous devriez juste de supprimer l'ambiguïté, je suis sûr que Clang, VC++ et GCC aura le même comportement alors. Car ce n'est assurément juste simplifié de l'extrait de qu'est-ce que votre code, pourriez-vous fournir plus d'informations? Pourquoi avez-vous besoin de deux surcharges de l'opérateur de même pour une classe?

* Ce qui me surprend, parce que d'habitude, VC++ est le seul qui n'est pas conforme à la norme quand il s'agit de modèles.

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