2010-05-28 5 views
3

Pourquoi VisualC++ (2008) est-il confondu 'C2666: 2 surcharges ont des conversions similaires' quand je spécifie une énumération comme deuxième paramètre, mais pas quand je définis un type booléen?Énumérations, surcharges constructeur avec conversions similaires

La correspondance de type ne devrait-elle pas exclure le second constructeur parce qu'il s'agit d'un type 'basic_string'?

#include <string> 
using namespace std; 

enum EMyEnum { mbOne, mbTwo }; 
class test { 
public: 
#if 1 // 0 = COMPILE_OK, 1 = COMPILE_FAIL 
    test(basic_string<char> myString, EMyEnum myBool2) { } 
    test(bool myBool, bool myBool2) { } 
#else 
    test(basic_string<char> myString, bool myBool2) { } 
    test(bool myBool, bool myBool2) { } 
#endif 
}; 

void testme() { 
    test("test", mbOne); 
} 

Je peux contourner ce problème en spécifiant une référence 'ie. string_string & myString 'mais pas si c'est' const basic_string & myString '.

Appelant aussi explicitement via "test ((basic_string)" test ", mbOne);" fonctionne aussi.

Je suppose que cela a quelque chose à voir avec le fait que chaque expression/type est résolu en un bool via un '! = 0' inhérent.

curieux commentaires tout de même :)

+0

L'une des meilleures descriptions de la résolution de surcharge peut être trouvée dans l'annexe B de [Modèles C++: Le Guide complet] (http://www.amazon.com/Templates-Complete-Guide-David-Vandevoorde/dp/0201734842). Le reste du livre est également excellent, mais cette annexe est une liste très succincte et facile à consulter des règles de résolution de surcharge. –

Répondre

5

La raison de l'ambiguïté est qu'une fonction candidate est meilleure qu'une autre fonction candidate que si aucun de ses paramètres sont plus mal correspondance que les paramètres de l'autre.

Le problème est que la chaîne littérale, qui a un type de const char[5] est convertible à la fois std::string (via un constructeur de conversion) et à un bool (depuis un tableau peut se décomposer à un pointeur, et tout pointeur est implicitement convertible en bool). La conversion vers bool est préférée car il s'agit d'une conversion standard et les conversions standard sont préférées aux conversions définies par l'utilisateur.

Alors, tenez compte des "cassés" surcharges:

test(basic_string<char> myString, EMyEnum myBool2) { } // (1) 
test(bool myBool, bool myBool2) { }      // (2) 

Le premier argument est un const char[5] et préfère (2) (par la description ci-dessus). Le deuxième argument est un EMyEnum et préfère (1), qui est une correspondance exacte; une conversion serait nécessaire pour correspondre à (2) (une énumération peut être implicitement convertie en bool).

Considérons maintenant le second cas:

test(basic_string<char> myString, bool myBool2) { } // (3) 
test(bool myBool, bool myBool2) { }     // (4) 

Le premier argument préfère encore (4), mais maintenant le deuxième argument peut correspondre à la fois (3) et (4) également. Ainsi, le compilateur peut sélectionner (4) et il n'y a pas d'ambiguïté.

Il n'y aurait pas d'ambiguïté si l'on éliminait la conversion requise pour le premier argument, par exemple,

test(basic_string<char>("test"), mbOne); 

parce que les deux arguments correspondraient (1) exactement.