2009-09-11 70 views
4

下面的代码编译在Visual C++和gcc,但未能与代码战士暧昧模板,代码战士

的抱怨是,在调用模板是模糊的 - doIt方法之间不能决定(M *)和doIt(M const *),即使在每种情况下,参数都是明确的成本或非常量。令人生气的是,如果我提供第二个模板参数,它决定它不再含糊不清。

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 

} 

这是Code Warrior编译器的错误吗? (或与gcc/Visual C++错误)。

+0

我不知道人们仍然使用良好的“代码战士”。他们不是不停止这样做吗? – 2009-09-11 23:59:05

回答

5

这是codewarrior编译器的错误。

这是应该发生的事情:

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 
} 

希望有所帮助。

+1

+1,尽管对于战士来说,C++ 03中的算法实际上并不能排序(尝试comeau 8/4/03,它不能排序),但它无法在两个方向上推导出“T1”。在http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#214修订的算法可以通过忽略“T1”来完成。我怀疑这就是更新的编译器所使用的,因为无论如何它都是直观的东西。但是当然,对于拒绝第一个电话的勇士来说,这是可耻的。 – 2009-09-12 01:28:40

+0

@litb - 良好的评论,当部分排列这些特定的调用时,它会引起人们注意返回类型的无关性 – 2009-09-12 04:18:24