Частичная специализация шаблона для указателя функции stdcall

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 модификатор. Это ошибка компилятора?

3 ответов


нет, это по дизайну. Соглашение о вызовах является очень большой частью объявления функции, функция шаблона использует соглашение о вызовах по умолчанию. Который не является __stdcall, если вы не компилируете с /Gz. Значение по умолчанию - /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);
};

что, конечно, не будет соответствовать R(__stdcall *)(T0, T1) на Win32, где __stdcall не игнорируется. Если вы хотите частично специализироваться на указателях функций, вам понадобится частичная спецификация для каждого соглашения о вызовах, которое вы хотите принять.


вы не специализировали свой шаблон для случая stdcall, т. е. вам нужно

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

Не уверен в синтаксисе, непроверенный, но это должно быть проблемой.