Частичная специализация шаблона для указателя функции __stdcall - PullRequest
8 голосов
/ 13 мая 2011
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:\project\orwell\head\multimapwizard\trunk\externals.cpp(49): error C2079: 't2' uses undefined class 'Externals::TFunction<F>'
1>          with
1>          [
1>              F=Externals::my_function_f2
1>          ]

Как вы можете видеть проблему с модификатором __stdcall.Это ошибка компилятора?

Ответы [ 3 ]

10 голосов
/ 13 мая 2011

Нет, это по замыслу. Соглашение о вызовах во многом является частью объявления функции, ваша шаблонная функция использует соглашение о вызовах по умолчанию. Что не является __stdcall, если вы не компилируете с / Gz. По умолчанию / Gd, __cdecl.

Код компилируется, когда вы нацеливаетесь на x64, потому что у него есть только одно соглашение о вызовах.

Fix:

template<class R, class T0, class T1>
class TFunction<R (__stdcall *)(T0,T1)>
{
    // etc..
};
4 голосов
/ 13 мая 2011

Это потому, что (*) означает соглашение о вызовах по умолчанию, которое составляет __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 не игнорируется. Если вы хотите частично специализироваться для указателей на функции, вам потребуется частичная спецификация для каждого соглашения о вызовах, которое вы хотите принять.

1 голос
/ 13 мая 2011

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

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

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

...