2009-09-11 12 views
4

Le code suivant compile dans Visual C++ et gcc, mais échoue avec le code guerriermodèle Ambigu, CodeWarrior

La plainte est que l'appel au modèle est ambigu - ne peut pas décider entre doIt (M *) et doIt (M const *), même si dans chaque cas, le paramètre est sans ambiguïté cost ou non-const. Irritant, si je fournis le deuxième argument de modèle, il décide qu'il n'est plus ambigu.

template< typename T1, typename T2 > 
T1 const* doIt(T2 const*); 

template< typename T1, typename T2 > 
T1* doIt(T2*); 

class M {}; 
class N : public M {}; 

void f() 
{ 
    M* m1 = NULL; 
    M const* m2 = NULL; 

    doIt<N>(m1); // Fail 
    doIt<N>(m2); // Fail 
    doIt<N,M>(m1); // OK 
    doIt<N,M>(m2); // OK 

} 

Est-ce juste une erreur avec le compilateur Code Warrior? (Ou et erreur avec gcc/Visual C++).

+0

Je ne savais pas que les gens utilisaient encore le bon vieux Code Warrior. N'ont-ils pas arrêté de faire ça? –

Répondre

5

C'est une erreur avec le compilateur codewarrior.

Voici ce qui devrait se produire:

template< typename T1, typename T2 > 
T1 const* doIt(T2 const*); // 1 

template< typename T1, typename T2 > 
T1* doIt(T2*); // 2 

class M {}; 
class N : public M {}; 

void f() 
{ 
    M* m1 = 0; 
    M const* m2 = 0; 

    doIt<N>(m1);  
    // In the above call - the compiler does the following (post argument deduction) 
    // 1) create a viable set of functions { N* doIt1<N,M>(const M*) , N* doIt2<N, M>(M*) } 
    // 2) check the conversion sequences - M* -> M* is better than M* -> const M* 
    // Since doIt2 has a "better" conversion sequence (hard to beat identity) it wins - no ambiguity 


    doIt<N>(m2);  
    // 1) Viable functions: { doIt1<N,M>(const M*), doIt2<N,const M>(const M*) } 
    // 2) Conversion Sequence Ranking: both do identity - so both are good 
    // 3) Check to see if the "mother" template of either candidate is more specialized 
    //  - Since doIt1 theoretically matches fewer types than doIt2, it is unambiguously more specialized (the standard specifies an algorithm to check this) 
    //  - so doIt1 wins 
} 

espoir qui aide.

+1

+1, bien que pour les crédits au guerrier, l'algorithme en C++ 03 ne pourrait en fait pas les ordonner (essayez comeau 8/4/03 qui ne parvient pas à commander aussi) - il échouerait en déduisant "T1" dans les deux sens. L'algorithme révisé à http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#214 peut le faire en ignorant "T1". Je pense que c'est ce que les compilateurs les plus récents utilisent, puisque c'est la chose intuitive de toute façon. Mais honte au guerrier d'avoir rejeté le premier appel, bien sûr. –

+0

@litb - bon commentaire, il attire l'attention sur le manque de pertinence du type de retour lors de la commande partielle de ces appels spécifiques –