我有以下类用于MSVC2013 Update 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'
答案 0 :(得分:2)
在MSVC中,调用约定是函数类型的一部分;默认调用约定为__cdecl
,因此R(Ts...)
实际为R __cdecl (Ts...)
且与int __stdcall(int)
不匹配。
如果您使用/Gz
进行编译,这会产生默认的调用约定__stdcall
,则会在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.