__stdcall函数指针的模板部分专用化

Template partial specialization for __stdcall function pointer

本文关键字:专用 板部 stdcall 函数 指针      更新时间:2023-10-16
typedef bool (*my_function_f)(int, double);
typedef bool (__stdcall *my_function_f2)(int, double);
//            ^^^^^^^^^
template<class F> class TFunction;
template<class R, class T0, class T1>
class TFunction<R(*)(T0,T1)>
{
  typedef R (*func_type)(T0,T1);
};
int main()
{
  TFunction<my_function_f> t1;  // works on x64 and win32
  TFunction<my_function_f2> t2; // works on x64 and doesn't work on win32
  return 0;
}

上面的代码在Visual C++ 2010中给了我以下错误:

1>e:projectorwellheadmultimapwizardtrunkexternals.cpp(49): error C2079: 't2' uses undefined class 'Externals::TFunction<F>'
1>          with
1>          [
1>              F=Externals::my_function_f2
1>          ]

如您所见,__stdcall修饰符存在问题。这是编译器错误吗?

不,这是设计使然。 调用约定是函数声明的重要组成部分,模板函数使用默认调用约定。 除非您使用/Gz 编译,否则这并不__stdcall。 默认值为/Gd,__cdecl。

代码在以 x64 为目标时进行编译,因为它只有一个调用约定。

修复:

template<class R, class T0, class T1>
class TFunction<R (__stdcall *)(T0,T1)>
{
    // etc..
};

这是因为 (*) 表示默认调用约定,即 __cdecl

template<class R, class T0, class T1>
class TFunction<R(*)(T0,T1)>
{
  typedef R (*func_type)(T0,T1);
};

实际上等于

template<class R, class T0, class T1>
class TFunction<R(__cdecl *)(T0,T1)>
{
  typedef R (__cdecl *func_type)(T0,T1);
};

当然,这与 Win32 上不会忽略__stdcallR(__stdcall *)(T0, T1)不匹配。如果要部分专用于函数指针,则需要为要接受的每个调用约定提供部分规范。

您没有针对 stdcall 情况专门化您的模板,即您需要

template<class R, class T0, class T1>
class TFunction<R(__stdcall *)(T0,T1)>
{
  typedef R (*func_type)(T0,T1);
};

不确定语法,未经测试,但这应该是问题所在。