2016-01-22 93 views
0

我有MSVC2013更新4使用了以下類:爲什麼這個模板不能編譯?

template <typename T> 
class MyFunction; 

template<typename R, class... Ts> 
class MyFunction < R(Ts...) > 
{ 
public: 
    using func_type = R(*)(Ts...); 

    MyFunction(func_type f) 
     : m_func(f) 
    { 
    } 

    R operator()(Ts ... args) 
    { 
     return m_func(args...); 
    } 

private: 
    func_type m_func; 
}; 

如果我使用它像這樣:

MyFunction<int (int)> f1(nullptr); 
MyFunction<int __cdecl(int)> f2(nullptr); 
MyFunction<int __stdcall(int)> f3(nullptr); 

爲什麼F3編譯失敗? (考慮到__cdecl的作品!)。

error C2079: 'f3' uses undefined class 'MyFunction<int (int)>' 
error C2440: 'initializing' : cannot convert from 'nullptr' to 'int'  
+1

'nullptr = NULL'。想想看。 –

+0

構造函數需要一個func_type,這是一個函數指針,因此nullptr很好? – paulm

+0

我懷疑'R(Ts ...)'隱含地是'R __cdecl(Ts ...)',所以部分特化不匹配'int __stdcall(int)'。 –

回答

2

在MSVC中,調用約定是函數類型的一部分;默認呼叫約定是__cdecl,所以R(Ts...)確實是R __cdecl (Ts...),並且不匹配int __stdcall(int)

如果使用默認調用約定__stdcall編譯爲/Gz,您會在f2上看到錯誤。

你必須寫偏特爲要支持所有的調用約定:

template<class F, class R, class... Args> 
class MyFunctionImpl { 
public: 
    using func_type = F*; 

    MyFunctionImpl(func_type f) 
     : m_func(f) 
    { 
    } 

    R operator()(Args ... args) 
    { 
     return m_func(args...); 
    } 

private: 
    func_type m_func; 
}; 

template<typename R, class... Ts> 
class MyFunction < R __cdecl(Ts...) > 
    : MyFunctionImpl<R __cdecl(Ts...), R, Ts...> { 
    using MyFunctionImpl<R __cdecl(Ts...), R, Ts...>::MyFunctionImpl; 
}; 

template<typename R, class... Ts> 
class MyFunction < R __stdcall(Ts...) > 
    : MyFunctionImpl<R __stdcall(Ts...), R, Ts...> { 
    using MyFunctionImpl<R __stdcall(Ts...), R, Ts...>::MyFunctionImpl; 
}; 

// etc.