3 votes

Opérateur de conversion C++ et résolution de surcharge

Étant donné cet exemple, qui comprend quelques surcharges :

#include 

class T
{
   public:
      operator const wchar_t *(void) const
      {
         std::cout << "Conversion" << std::endl;
         return L"Testing";
      }
};

template 
class A
{
};

template 
void operator <<(A &, const T *)
{
   std::cout << "1" << std::endl;
}

template 
void operator <<(A &, const void *)
{
   std::cout << "2" << std::endl;
}

int main(void)
{
   A test;
   T          source;

   test << L"1";
   test << static_cast(source);
   test << source;
}

Et sa sortie :

1
Conversion
1
Conversion
2

Ma question est - pourquoi void operator <<(A &, const void *) est-il appelé pour l'instruction test << source; ? Quelqu'un peut-il citer une partie spécifique de la norme qui couvre ce cas ?

4voto

James Kanze Points 96599

Parce que la déduction des arguments de modèle ne prend pas en compte les conversions implicites définies par l'utilisateur. Le résultat est que lorsque vous avez écrit :

test << source;

, le compilateur n'a pas pu trouver un T adapté pour le premier modèle de fonction ; il essaie de trouver un T tel que T const* a le même type que votre T, ce qui n'est pas possible. La déduction des arguments échoue, et aucune instance du modèle n'est ajoutée à l'ensemble de surcharges. Puisqu'il n'y a pas d'argument du modèle dans le deuxième paramètre du deuxième modèle de fonction, il n'y a pas de déduction d'argument qui échoue, et l'instance résultante devient le seul membre de l'ensemble de surcharges, et est donc choisie.

0voto

Mark B Points 60200

Il utilise la conversion implicite de T en wchar_t. Tout type est convertible en void* donc le compilateur appelle cette version de l'opérateur operator<<. L'opérateur T* n'a jamais été une option car il n'y avait aucun moyen d'obtenir implicitement un T* à partir d'un T. Vouliez-vous dire le faire un opérateur T& << ?

0voto

Grizzly Points 11329

La déduction implicite des arguments de modèle ne prendra pas en compte les conversions implicites définies par l'utilisateur. Ainsi, l'appel de template void operator <<(A &, const T *) déduirait que T est wchar_t à partir du premier argument, mais le second argument est T au lieu de const wchar_t*. Par conséquent, le compilateur échouera à faire correspondre cet opérateur.

Pour template void operator <<(A &, const void *), la situation est différente : T sera déduit comme étant wchar_t à partir du premier argument de fonction. Le deuxième argument peut être converti implicitement en const wchar_t* par une conversion définie par l'utilisateur, qui peut ensuite être implicitement converti en const void* par une conversion intégrée. Par conséquent, cette fonction peut être appelée avec ces arguments et est utilisée, puisque l'autre ne pouvait pas être déduite.

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