Template partial specialization for __stdcall function pointer
Asked Answered
K

3

8
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;
}

The code above gives me the following error in 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>          ]

As you can see the problem with __stdcall modifier. Is this the compiler bug?

Keratogenous answered 13/5, 2011 at 12:0 Comment(3)
__stdcall: "On Itanium Processor Family (IPF) and x64 processors, __stdcall is accepted and ignored by the compiler", which I guess is why it works 64-bit.Neoterism
https://mcmap.net/q/1325251/-__stdcall-typedef-g-problem might helpPraxis
@Praxis isn't he already using that syntax?Neoterism
P
10

No, this is by design. The calling convention is very much part of the function declaration, your template function uses the default calling convention. Which is not __stdcall unless you compile with /Gz. The default is /Gd, __cdecl.

The code compiles when you target x64 because it blissfully has only one calling convention.

Fix:

template<class R, class T0, class T1>
class TFunction<R (__stdcall *)(T0,T1)>
{
    // etc..
};
Plank answered 13/5, 2011 at 12:16 Comment(0)
Z
4

This is because (*) means default calling convention, which is __cdecl.

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

is actually equal to

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

which, of course, will not match an R(__stdcall *)(T0, T1) on Win32 where __stdcall is not ignored. If you want to partially specialize for function pointers then you will need a partial spec for every calling convention you want to accept.

Zambrano answered 13/5, 2011 at 12:16 Comment(0)
X
1

You have not specialized your template for the stdcall case, i.e. you need

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

Not sure about the syntax, untested, but that should be the issue.

Xeres answered 13/5, 2011 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.