6

下面的代碼,它試圖專門類模板「特殊」的基礎上,成員函數指針類型的返回類型,導致編譯錯誤與VC9:類模板部分特例參數化上的成員函數的返回類型

template<class F> struct special {}; 
template<class C> struct special<void(C::*)()> {}; 
template<class R, class C> struct special<R(C::*)()> {}; 

struct s {}; 

int main() 
{ 
    special<void(s::*)()> instance; 
    return 0; 
} 

錯誤C2752: '特殊':一個以上的部分特匹配

相同的代碼是由GCC-4.3.4接受,如圖中的模板的參數列表:http://ideone.com/ekWGg
這是VC9中的一個錯誤嗎?如果是這樣,這個錯誤會持續到VC10嗎?

我已經然而想出一個窘況侵入性的解決方法(對於這個特定的使用情況下,至少更普遍的解決方案表示歡迎。):

#include <boost/function_types/result_type.hpp> 
#include <boost/type_traits/is_same.hpp> 

template<typename F, typename R> 
struct is_result_same : 
    boost::is_same< 
    typename boost::function_types::result_type<F>::type, 
    R 
    > 
{}; 

template<class F, bool = is_result_same<F, void>::value> 
struct special {}; 

template<class R, class C> struct special<R(C::*)(), true> {}; 
template<class R, class C> struct special<R(C::*)(), false> {}; 
+0

我想這是因爲當解決R爲'void'的情況時,兩種專業化的簽名實際上是相同的......一些聰明的'typename'關鍵字的使用可能會有幫助,但我現在無法想到任何聰明的東西。 – AJG85 2011-02-24 22:02:01

回答

3

這是一個錯誤。

template <class C> struct special<void(C::*)()>;  // specialization 1 
template <class R, class C> struct special<R(C::*)()>; // specialization 2 

根據14.5.4.2,這兩個類模板特的部分排序是一樣的,這些虛函數模板部分排序:

template <class C> void f(special<void(C::*)()>);  // func-template 3 
template <class R, class C> void f(special<R(C::*)()>); // func-template 4 

根據14.5.5.2,部分這兩個函數模板的排序是通過用一個參數列表中的每個類型模板參數代替發明的類型並且使用另一個函數模板中的參數列表嘗試模板參數推導來確定的。

// Rewrite the function templates with different names - 
// template argument deduction does not involve overload resolution. 
template <class C> void f3(special<void(C::*)()>); 
template <class R, class C> void f4(special<R(C::*)()>); 

struct ty5 {}; struct ty6 {}; struct ty7 {}; 
typedef special<void(ty5::*)()> arg3; 
typedef special<ty6 (ty7::*)()> arg4; 

    // compiler internally tests whether these are well-formed and 
    // the resulting parameter conversion sequences are "exact": 
    f3(arg4()); 
    f4(arg3()); 

模板參數推導的細節在14.8.2中。有效扣除額從template_name<dependent_type>dependent_type1 (dependent_type2::*)(arg_list)。所以f4(arg3())演繹成功,推導出f4<void,ty5>(arg3());。因爲voidty6不統一,所以f3(arg4())扣除顯然可能永遠不會成功。

因此函數模板3比函數模板4和類模板特更專業的1比類模板特更專業化2.因此,儘管special<void(s::*)()>都特的比賽,它明確地實例化專業化1.

相關問題