Соглашение о вызовах & quot; определяет & quot; без #define

В Microsoft WinDef.h введено несколько #defines для обратных вызовов:

#ifdef _MAC
#define CALLBACK    PASCAL
#define WINAPI      CDECL
#define WINAPIV     CDECL
#define APIENTRY    WINAPI
#define APIPRIVATE  CDECL
#ifdef _68K_
#define PASCAL      __pascal
#else
#define PASCAL
#endif
#elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define CALLBACK    __stdcall
#define WINAPI      __stdcall
#define WINAPIV     __cdecl
#define APIENTRY    WINAPI
#define APIPRIVATE  __stdcall
#define PASCAL      __stdcall
#else
#define CALLBACK
#define WINAPI
#define WINAPIV
#define APIENTRY    WINAPI
#define APIPRIVATE
#define PASCAL      pascal
#endif

Есть ли способ сделать что-то подобное без макроса препроцессора?
Я хотел бы иметь что-то, что разрешает различные соглашения о вызовах в Unix и Windows, но что — в отличие от макроса — может быть пространством имен.

Я пробовал «typedef __stdcall test»; но это не компилируется.

РЕДАКТИРОВАТЬ — вот пример сценария использования:

namespace Thread
{
typedef startRoutineReturnType (startRoutineCallingConvention *startRoutineCallback)(void* pArg);
}

Thread::startRoutineReturnType Thread::startRoutineCallingConvention startRoutine(void* pArg);

Таким образом startRoutine может подтвердить подпись этого обратного вызова на всех платформах, хотя соглашение о вызовах обратного вызова различается для разных платформ.
Когда существует вероятность того, что многие функции должны подтвердить эту сигнатуру обратного вызова, то что-то вроде

#ifdef UNIX
void* foo(void* pArg)
#elif WINDOWS
DWORD WINAPI foo(LPVOID pArg)
#else
// something else
#endif
{
// body
}

вместо этого выглядит довольно грязно.

4

Решение

На мой взгляд, это ужасный взлом, но я попытался понять, смогу ли я сделать это с помощью специализаций по шаблонам, и это действительно сработало. Попробуй это:

#include <iostream>

enum CALLCONVENTION
{
STDCALL,
CDECL
};

template <CALLCONVENTION Convention>
void Function()
{
}

template<>
void __stdcall Function<STDCALL>()
{
std::cout << "STDCALL" << std::endl;
}

template<>
void __cdecl Function<CDECL>()
{
std::cout << "CDECL" << std::endl;
}

namespace StdCall
{
void Foo()
{
Function<STDCALL>();
}
}

namespace CDecl
{
void Foo()
{
Function<CDECL>();
}
}

int main(void)
{
Function<STDCALL>();
Function<CDECL>();
StdCall::Foo();
CDecl::Foo();

return 0;
}

Компилируется и работает на Visual Studio 2010.

2

Другие решения

Других решений пока нет …