可变参数宏中的 C++ 可变参数模板函数
C++ variadic templates function in variadic macro
我目前正在从事一个需要简化现有系统的项目。
Wihtout 进入细节问题是我得到了一些函数指针(来自类型:void*),我需要从它创建一个函数(= 创建一个带有签名的函数)。所以我的方法是创建以下可变模板函数:
template <typename ReturnType, typename ... Params>
ReturnType(*GetFunction(void* func, Params ...)) (Params ...)
{
return reinterpret_cast<ReturnType(*) (Params ...)> (func);
}
现在我需要一种方法来创建所需的函数:
#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));\
}
这就是问题所在。 (我认为)Params 没有按照它们应该扩展的方式扩展。但是不知道为什么?
我用硬编码值测试了 DEFINE_FUNCTION 宏中的 FUNCTION_DIRECTCALL(简单地将定义放入 directcall 中)并且它有效,所以不应该有错误,但我愿意改进
#define FUNCTION_DIRECTCALL(returnType, functionName, ...) \
GetFunction<returnType>(functionName, DECLARE_PARAMS __VA_ARGS__) ( DECLARE_PARAMS __VA_ARGS__)
如果我尝试用宏定义函数
Define_Function(void, ThatFunction, (int a_, int b_)); // void ThatFunction(int a, int b);
我收到以下错误:"Severity Code Description Project File Line Suppression State Error (active) incomplete type is not allowed [...]\main.cpp 34"
所以我的问题是,我做错了什么?问题真的与 DEFINE_FUNCTION 宏中的参数有关还是我遗漏了什么?
我使用过宏,但我不会称自己为该领域的专家。但我的理解是 (DECLARE_PARAMS Params) 应该将参数扩展为:
int a_, int b_
扫描后我会得到以下代码:
void Gen_ThatFunction(int a_, int b_)
{
return GetFunction<void>(ThatFunction, a_, b_) (a_, b_);
}
测试 Directcall 宏:
使用以下代码我测试了 directcall 宏的功能
因此我更改了 Define_Function 宏:
#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params) \
{\
int a = 2, b = 3;\
return FUNCTION_DIRECTCALL(void, ThatFunction, (a, b) );\
}
ThatFunction 的定义:
void ThatFunction(int a, int b)
{
std::cout << a << " * " << b << " = " << b * a << std::endl;
}
输出:“2 * 3 = 6”
所有代码编译于VC++ 2015
我知道如何做你所要求的唯一方法真的很笨拙。
#define DEFINE_FUNCTION(RET, NAME, TYPES, NAMES, BOTH) RET Gen_##NAME BOTH { return reinterpret_cast<RET(*)TYPES>(NAME) NAMES; }
你这样使用它:
DEFINE_FUNCTION(void, ThatFunction, (int, int), (a_, b_), (int a_, int b_))
return void*
(或函数)的类型和名称是前两个参数。接下来是用括号括起来的参数类型列表,也包括括起来的参数名称,最后是括起来的类型和名称。就像我说的,笨重。
这将生成函数:
void Gen_ThatFunction (int a_, int b_) { return reinterpret_cast<void(*)(int, int)>(ThatFunction) (a_, b_); }
然后您可以随意调用该函数:
Gen_ThatFunction(2, 3); //prints "2 * 3 = 6"
当然,请记住这是 Microsoft 特有的。此处,括号内的逗号分隔项是单个宏参数。在任何其他编译器上,这都行不通(据我所知)。
我目前正在从事一个需要简化现有系统的项目。 Wihtout 进入细节问题是我得到了一些函数指针(来自类型:void*),我需要从它创建一个函数(= 创建一个带有签名的函数)。所以我的方法是创建以下可变模板函数:
template <typename ReturnType, typename ... Params>
ReturnType(*GetFunction(void* func, Params ...)) (Params ...)
{
return reinterpret_cast<ReturnType(*) (Params ...)> (func);
}
现在我需要一种方法来创建所需的函数:
#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));\
}
这就是问题所在。 (我认为)Params 没有按照它们应该扩展的方式扩展。但是不知道为什么?
我用硬编码值测试了 DEFINE_FUNCTION 宏中的 FUNCTION_DIRECTCALL(简单地将定义放入 directcall 中)并且它有效,所以不应该有错误,但我愿意改进
#define FUNCTION_DIRECTCALL(returnType, functionName, ...) \
GetFunction<returnType>(functionName, DECLARE_PARAMS __VA_ARGS__) ( DECLARE_PARAMS __VA_ARGS__)
如果我尝试用宏定义函数
Define_Function(void, ThatFunction, (int a_, int b_)); // void ThatFunction(int a, int b);
我收到以下错误:"Severity Code Description Project File Line Suppression State Error (active) incomplete type is not allowed [...]\main.cpp 34"
所以我的问题是,我做错了什么?问题真的与 DEFINE_FUNCTION 宏中的参数有关还是我遗漏了什么?
我使用过宏,但我不会称自己为该领域的专家。但我的理解是 (DECLARE_PARAMS Params) 应该将参数扩展为:
int a_, int b_
扫描后我会得到以下代码:
void Gen_ThatFunction(int a_, int b_)
{
return GetFunction<void>(ThatFunction, a_, b_) (a_, b_);
}
测试 Directcall 宏: 使用以下代码我测试了 directcall 宏的功能
因此我更改了 Define_Function 宏:
#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params) \
{\
int a = 2, b = 3;\
return FUNCTION_DIRECTCALL(void, ThatFunction, (a, b) );\
}
ThatFunction 的定义:
void ThatFunction(int a, int b)
{
std::cout << a << " * " << b << " = " << b * a << std::endl;
}
输出:“2 * 3 = 6”
所有代码编译于VC++ 2015
我知道如何做你所要求的唯一方法真的很笨拙。
#define DEFINE_FUNCTION(RET, NAME, TYPES, NAMES, BOTH) RET Gen_##NAME BOTH { return reinterpret_cast<RET(*)TYPES>(NAME) NAMES; }
你这样使用它:
DEFINE_FUNCTION(void, ThatFunction, (int, int), (a_, b_), (int a_, int b_))
return void*
(或函数)的类型和名称是前两个参数。接下来是用括号括起来的参数类型列表,也包括括起来的参数名称,最后是括起来的类型和名称。就像我说的,笨重。
这将生成函数:
void Gen_ThatFunction (int a_, int b_) { return reinterpret_cast<void(*)(int, int)>(ThatFunction) (a_, b_); }
然后您可以随意调用该函数:
Gen_ThatFunction(2, 3); //prints "2 * 3 = 6"
当然,请记住这是 Microsoft 特有的。此处,括号内的逗号分隔项是单个宏参数。在任何其他编译器上,这都行不通(据我所知)。