假设我有一个宏:
#define FOO(a, ...) if (a) foo(a, ## __VA_ARGS__)
这很好用:
-
FOO(a)
将转换为if (a) foo(a)
-
FOO(a, <some_parameters>)
将转换为if (a) foo(a, <some_parameters>)
是否可以修改这个宏,所以只有__VA_ARGS__
的第一个参数(如果存在)传递给 foo
?所以,我需要:
-
FOO(a)
转换为if (a) foo(a)
-
FOO(a, b, <some_parameters>)
转换为if (a) foo(a, b)
我试图用与 BOOST_PP_VARIADIC_SIZE
相同的想法来解决这个问题有,但结果这个宏返回1
对于 BOOST_PP_VARIADIC_SIZE()
(空参数),这不是预期的(我预期 0
)。
请注意,我需要一个解决方案,其中 b
和 <some_parameters>
仅在 bool(a)
时评估是true
.
最佳答案
我建议使用带有通用 lambda 的可变参数宏作为解决方案。 要点如下:
很难将
a
和__VA_ARGS__
作为宏中传递的参数传递给 lambda,因为当__VA_ARGS__
为空时[](){...}(a, __VA_ARGS__)
成为
[](){...}(a,)
和这个
,
导致编译错误。 因此我们将FOO
的第一个和第二个参数分别拆分为捕获的和传递的,如下所示。 然后,即使__VA_ARGS__
为空,我们也可以在宏中使用通用 lambda。[a](){...}(__VA_ARGS__)
__VA_ARGS__
的大小可以在编译时计算为constexpr auto N
。然后我们可以使用if constexpr
来分隔函数调用。我们还可以应用带初始化器的 if 语句,这是从 C++17 引入的
if(a)
。
那么建议的宏如下。 这也适用于您。
#include <tuple>
#define FOO(a, ...) \
if(const bool a_ = (a); a_) \
[a_](auto&&... args) \
{ \
const auto t = std::make_tuple(std::forward<decltype(args)>(args)...); \
constexpr auto N = std::tuple_size<decltype(t)>::value; \
\
if constexpr( N==0 ) { \
return foo(a_); \
} \
else { \
return foo(a_, std::get<0>(t)); \
} \
}(__VA_ARGS__)
关于c++ - 提取 __VA_ARGS__ 的第一个参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53597804/