C++ Macro Magic:为每个宏参数获取参数计数
C++ Macro Magic: getting for every macro parameter, the parameter count number
我要写很多这样的代码。
foo.setArg(0, arg_0);
foo.setArg(1, arg_1);
...
foo.setArg(n, arg_n);
其中 n 是编译时特定的,arg_n 是不同的类型;
我想要一个可以这样调用的可变参数宏
MACRO_MAGIC(arg_0,arg_1,...,arg_n)
我知道如何获取参数总数,但我没有成功管理它。
编辑: from (non-sense) statement n is runtime specific to compile-time specific
有时候,我好像也不得不这样写代码,还好我很快就找到了替代方案。在那些我不知道的情况下,我(在本地!)构建这样的宏(以防止复制粘贴错误):
#define SET_FOO(num) foo.setArg(num, arg_##num);
SET_FOO(1)
SET_FOO(2)
#undef SET_FOO
是的:它相当原始,绝对不是火箭安全的,但它有帮助。
您可以为此使用可变参数模板:
namespace detail
{
template <std::size_t ... Is, typename ... Ts>
void SetFoo(Foo& foo, std::index_sequence<Is...>, Ts&&... args)
{
int dummy[] = {0, (foo.setArg(Is, args), void(), 0)...};
(void) dummy; // Remove warning for unused variable
}
}
template <typename ... Ts>
void SetFoo(Foo& foo, Ts&&... args)
{
detail::SetFoo(foo, std::index_sequence_for<Ts...>(), std::forward<Ts>(args)...);
}
或使用 C++17,使用折叠表达式:
namespace detail
{
template <std::size_t ... Is, typename ... Ts>
void SetFoo(Foo& foo, std::index_sequence<Is...>, Ts&&... args)
{
(static_cast<void>(foo.setArg(Is, args)), ...);
}
}
我自己找到了答案:
#define IT_CHOOSER2(name,count) name##count
#define IT_CHOOSER1(name,count) IT_CHOOSER2(name,count)
#define IT_CHOOSER(name,count) IT_CHOOSER1(name,count)
#define IT_SET_ARGS_PREFIX IT_SET_ARGS_
#define IT_SET_ARGS_1( foo, arg_1) kernel.setArg(0, arg_1)
#define IT_SET_ARGS_2( foo, arg_1, arg_2) kernel.setArg(0, arg_1); kernel.setArg(1, arg_2)
...
#define IT_SET_ARGS(foo,...)\
IT_GLUE(IT_CHOOSER(IT_SET_ARGS_PREFIX,IT_N_ARGS(__VA_ARGS__)), (kernel,__VA_ARGS__))
但我想提一下,如果 c++11 可用,Jarod42 解决方案会更好。
我要写很多这样的代码。
foo.setArg(0, arg_0);
foo.setArg(1, arg_1);
...
foo.setArg(n, arg_n);
其中 n 是编译时特定的,arg_n 是不同的类型;
我想要一个可以这样调用的可变参数宏
MACRO_MAGIC(arg_0,arg_1,...,arg_n)
我知道如何获取参数总数,但我没有成功管理它。
编辑: from (non-sense) statement n is runtime specific to compile-time specific
有时候,我好像也不得不这样写代码,还好我很快就找到了替代方案。在那些我不知道的情况下,我(在本地!)构建这样的宏(以防止复制粘贴错误):
#define SET_FOO(num) foo.setArg(num, arg_##num);
SET_FOO(1)
SET_FOO(2)
#undef SET_FOO
是的:它相当原始,绝对不是火箭安全的,但它有帮助。
您可以为此使用可变参数模板:
namespace detail
{
template <std::size_t ... Is, typename ... Ts>
void SetFoo(Foo& foo, std::index_sequence<Is...>, Ts&&... args)
{
int dummy[] = {0, (foo.setArg(Is, args), void(), 0)...};
(void) dummy; // Remove warning for unused variable
}
}
template <typename ... Ts>
void SetFoo(Foo& foo, Ts&&... args)
{
detail::SetFoo(foo, std::index_sequence_for<Ts...>(), std::forward<Ts>(args)...);
}
或使用 C++17,使用折叠表达式:
namespace detail
{
template <std::size_t ... Is, typename ... Ts>
void SetFoo(Foo& foo, std::index_sequence<Is...>, Ts&&... args)
{
(static_cast<void>(foo.setArg(Is, args)), ...);
}
}
我自己找到了答案:
#define IT_CHOOSER2(name,count) name##count
#define IT_CHOOSER1(name,count) IT_CHOOSER2(name,count)
#define IT_CHOOSER(name,count) IT_CHOOSER1(name,count)
#define IT_SET_ARGS_PREFIX IT_SET_ARGS_
#define IT_SET_ARGS_1( foo, arg_1) kernel.setArg(0, arg_1)
#define IT_SET_ARGS_2( foo, arg_1, arg_2) kernel.setArg(0, arg_1); kernel.setArg(1, arg_2)
...
#define IT_SET_ARGS(foo,...)\
IT_GLUE(IT_CHOOSER(IT_SET_ARGS_PREFIX,IT_N_ARGS(__VA_ARGS__)), (kernel,__VA_ARGS__))
但我想提一下,如果 c++11 可用,Jarod42 解决方案会更好。