Search code examples
c++templatescalling-convention

How to know whether a calling convention is in use with a Qt project?


You know, when you define a function, you can define it's calling convention at the same time, like this:

int __stdcall foo(int) { return 1; };
int __cdecl   bar(int) { return 1; };

And if you want to use this function to deduce template parameters, you have to deal with the calling convention, eg:

template<typename T> void tmpl_func( T( __stdcall f )(T) ) { other_func<T>(); };

With this template, you can only use "foo" as the parameter. If you use "bar", it can't be compiled.

tmpl_func(foo);   // ok
tmpl_func(bar);   // err

So, if you have a function that uses __cdecl, you have to define the template functions with both calling conventions, like this:

template<typename T> void tmpl_func( T( __stdcall f )(T) ) { other_func<T>(); };
template<typename T> void tmpl_func( T( __cdecl   f )(T) ) { other_func<T>(); };

And foo instantiate the __stdcall version, bar instantiate the __cdecl version, no redefinition.

In general, this works well, but recently i met a problem:

In a Qt project, when i define template functions in the way i said above, the compiler said :__cdecl template function has already defined.

And if you only define tmpl_func in __stdcall version, it also can use bar as it's parameter.

Is this means that all the calling convention identifiers i wrote just dont work, and all functions are called in __cdecl way?

Why and how could i know whether this situation will happen? Can i check it using macros or compile options?

Sorry for my bad english, I wish i had made it clear, but this do troubles me for some time.


Solution

  • You know, when you define a function, you can define it's calling convention at the same time

    This is wrong. What you describe is a (vendor specific) extension to C++. For example, on my GCC compiler on Linux, it probably won't work.

    In a Qt project,

    Don't use at all any explicit __stdcall or __cdecl annotation in your Qt code.

    (using that in your Qt code is shooting yourself in your foot: it hurts badly; stick to standard C++11 code for a Qt5 project)

    If you need to call some external weird function (with a strange & explicit calling convention) write some extern "C" (or some static inline one, if it is short) wrapping function doing that (and your wrapping function has a usual signature, without explicit calling convention annotation).

    Pragmatically, when coding a Qt project, you compile it with all warnings & debug info (so g++ -Wall -g if using GCC), you debug it with your gdb debugger, and you later optimize (e.g. compile with g++ -Wall -g -O2) it -e.g. for benchmarking and production code- and you trust the compiler to optimize well, inline many function calls, and choose good enough calling conventions. Don't mess with calling conventions in your Qt code.

    (implicitly you are asking if and how __stdcall or __cdecl is changing the type system of C++; and C++ types are complex enough already, you don't want even more mess)