简体   繁体   中英

C++ variadic templates function in variadic macro

I'm currently working on a project where I need to simplfy an existing system. Wihtout going into the details the problem is that I get some function pointer (from type: void*) and I need to create a function from it (= create a function with signature). So my approach was to create the following variadic template function:

template <typename ReturnType, typename ... Params>
ReturnType(*GetFunction(void* func, Params ...)) (Params ...)
{
    return reinterpret_cast<ReturnType(*) (Params ...)> (func);
}

Now I need a way to create the needed functions:

#define DECLARE_PARAMS(...) __VA_ARGS__

#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params)\
{\
    return  FUNCTION_DIRECTCALL(returnType, fname, (DECLARE_PARAMS Params));\
}

and here is the Problem. (I think) the Params don't expand the way they should expand. But I don't know why?

I tested the FUNCTION_DIRECTCALL in the DEFINE_FUNCTION macro with hardcoded values (simple put the defintion into the directcall) and it worked so there shouldn't be an error but I'm open for improvements

#define FUNCTION_DIRECTCALL(returnType, functionName, ...) \
GetFunction<returnType>(functionName, DECLARE_PARAMS __VA_ARGS__) ( DECLARE_PARAMS __VA_ARGS__)

If I try to define a function with the macro

Define_Function(void, ThatFunction, (int a_, int b_)); // void ThatFunction(int a, int b);

I get the following error: "Severity Code Description Project File Line Suppression State Error (active) incomplete type is not allowed [...]\\main.cpp 34"

So my question is, what am I doing wrong? Is the problem really related to the Params in the DEFINE_FUNCTION macro or did I miss something?

I worked with macros but I wouldn't call myself an expert in this area. But the way I understand it is that (DECLARE_PARAMS Params) should expand the params to:

int a_, int b_

and after the scan I would expect the following code:

void Gen_ThatFunction(int a_, int b_)
{
    return GetFunction<void>(ThatFunction, a_, b_) (a_, b_);
}

Testing the Directcall macro: with the following code I tested the functionality of the directcall macro

Therefore I change the Define_Function macro:

#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params)   \
{\
    int a = 2, b = 3;\
    return  FUNCTION_DIRECTCALL(void, ThatFunction, (a, b) );\
}

The definition of ThatFunction:

void ThatFunction(int a, int b)
{
    std::cout <<  a << " * " << b << " = " << b * a << std::endl;
}

output: "2 * 3 = 6"

All code compiled in VC++ 2015

The only way I know how to do what you're asking is really clunky.

#define DEFINE_FUNCTION(RET, NAME, TYPES, NAMES, BOTH) RET Gen_##NAME BOTH { return reinterpret_cast<RET(*)TYPES>(NAME) NAMES;  }

You use it like:

DEFINE_FUNCTION(void, ThatFunction, (int, int), (a_, b_), (int a_, int b_))

The return type and name of the void* (or function) are the first two parameters. Next is the list of the argument types enclosed by parenthesis, the argument names enclosed as well, and lastly the enclosed types AND names. Like I said, clunky.

This would generate the function:

void Gen_ThatFunction (int a_, int b_) { return reinterpret_cast<void(*)(int, int)>(ThatFunction) (a_, b_); }

You can then call the function as you wish:

Gen_ThatFunction(2, 3); //prints "2 * 3 = 6"

Of course, keep in mind this is Microsoft specific. Here, comma separated items enclosed by parenthesis are a single macro parameter. On any other compiler, this wouldn't work (that I'm aware of).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM