2016-01-22 92 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.