我想创建一个神奇的宏,或任何会产生这样的东西:
MAGICAL_MACRO(return_type, method_name, ...)
应该像这样工作:
MAGICAL_MACRO(void, Foo, int a, int b)
- >
virtual void Foo(int a, int b)
{
_obj->Foo(a, b);
}
这可能吗?恐怕不是。
答案 0 :(得分:5)
两个问题:您是否对MAGIC_MACRO
的参数略有不同的语法?您可以使用Boost.Preprocessor仅限标头的库吗?
如果两个答案都是"是",我有一个解决方案:
#define MAGICAL_MACRO(Type, Name, ...) \
virtual Type Name(MAGICAL_GENERATE_PARAMETERS(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))) {\
_obj->Name(MAGICAL_GENERATE_ARGUMENTS(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))); \
}
#define MAGICAL_GENERATE_PARAMETERS(Args) \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(MAGICAL_MAKE_PARAMETER, %%, Args))
#define MAGICAL_GENERATE_ARGUMENTS(Args) \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(MAGICAL_MAKE_ARGUMENT, %%, Args))
#define MAGICAL_MAKE_PARAMETER(s, Unused, Arg) \
BOOST_PP_TUPLE_ELEM(2, 0, Arg) BOOST_PP_TUPLE_ELEM(2, 1, Arg)
#define MAGICAL_MAKE_ARGUMENT(s, Unused, Arg) \
BOOST_PP_TUPLE_ELEM(2, 1, Arg)
用法如下:
MAGICAL_MACRO(void, Foo, (int, a), (int, b))
宏定义中使用的%%
只是我指示的方式"不使用此值。"你可以在那里使用其他任何东西(除非它包含逗号)。
只要所涉及的类型没有拼写逗号,上述解决方案就会起作用。如果是,请为它们引入类型别名(typedef
或using
)。请注意, 可以在预处理器魔术本身内解决这个问题,但它使已经很难看的代码变得复杂。
答案 1 :(得分:4)
如果您不介意更改宏参数的语法,可以使用以下技巧滥用声明语法:
#define MAGICAL_MACRO(return_type, method_name, ...) \
virtual return_type method_name(__VA_ARGS__)
{ \
_obj->method_name(__VA_ARGS__); \
}
MAGICAL_MACRO(void, foo, int(a), int(b))
那将扩展为:
virtual void foo(int(a), int(b))
{
_obj->foo(int(a), int(b));
}
void func(int(a), int(b))
完全等同于void func(int a, int b)
。
额外的强制转换(或构造函数调用取决于参数类型)是丑陋的,但GCC和Clang(带-O0
)似乎都忽略了它们,不仅对于原始类型/ POD,而且对于非POD类即使他们的副本构造函数有副作用:
#include <iostream>
struct A
{
int x;
A(int value) : x(value) {}
A(const A &o)
{
x = o.x;
std::cout << "copy";
}
};
void func(A a)
{
std::cout << a.x << '\n';
}
void func1(A a)
{
func(a);
}
void func2(A a)
{
func(A(a));
}
int main()
{
func1(1); // prints `copy1`
func2(2); // prints `copy2`
}
答案 2 :(得分:2)
以下代码适用于您所要求的最多1024个参数以及不使用使用其他内容(如boost)。它定义了一个this.axios.post('url', this.form).then(...
和一个EVAL(...)
宏来进行递归,并为每个迭代使用宏MAP(m, first, ...)
和下一个参数m
。
主要是从C Pre-Processor Magic复制的。那里的解释也很棒。您也可以在此git repository下载first
这样的辅助宏,实际代码中也有很多解释。它是可变的,所以它需要你想要的参数数量。
但是我更改了EVAL(...)
和FIRST
宏,因为它使用了Gnu扩展名,就像我在源代码中复制了它一样。
要将SECOND
等参数拆分为int a
和int
我使用this answer from SO。
你的宏将是:
a
示例和限制:
#define MAGICAL_MACRO(return_type, method_name, ...) \
virtual return_type method_name(__VA_ARGS__) \
{ \
return _obj->method_name(EVAL(MAP(TYPE_NAME, __VA_ARGS__))); \
}
需要所有其他宏,请注意需要在每个宏中定义类型拆分:
MAGICAL_MACRO(void, FOO, int a, double b, char c);
--> virtual void FOO(int a, double b, char c) { return _obj->FOO(a , b , c); };
MAGICAL_MACRO(int, FOO, int a, double b, char c);
--> virtual int FOO(int a, double b, char c) { return _obj->FOO(a , b , c); } ;
MAGICAL_MACRO(void, FOO, int* a, double* b, char* c);
--> virtual void* FOO(int* a, double* b, char* c) { return _obj->FOO(* a , * b , * c); };
/* maybe not what you want: pointer are dereferenced */