C++ 提取uu VA_参数的第一个参数__
假设我有一个宏:C++ 提取uu VA_参数的第一个参数__,c++,c++17,C++,C++17,假设我有一个宏: #define FOO(a, ...) if (a) foo(a, ## __VA_ARGS__) 这很有效: FOO(a)将转换为if(a)FOO(a) FOO(a,)将转换为if(a)FOO(a,) 是否可以修改此宏,以便只将\uu VA\u ARGS\uu的第一个参数(如果存在)传递给foo?因此,我需要: FOO(a)如果(a)FOO(a) FOO(a,b,)要转换为if(a)FOO(a,b) 我试图用与BOOST\u PP\u VARIADIC\u SIZE
#define FOO(a, ...) if (a) foo(a, ## __VA_ARGS__)
这很有效:
将转换为FOO(a)
if(a)FOO(a)
将转换为FOO(a,)
if(a)FOO(a,)
\uu VA\u ARGS\uu
的第一个参数(如果存在)传递给foo
?因此,我需要:
如果(a)FOO(a)FOO(a)
要转换为FOO(a,b,)
if(a)FOO(a,b)
BOOST\u PP\u VARIADIC\u SIZE
相同的想法来解决这个问题,但结果是,对于BOOST\u PP\u VARIADIC\u SIZE()
(空参数),这个宏返回1
,这是不期望的(我期望0
)
请注意,我需要一个解决方案,其中只有当bool(a)
为true
时才对b
和
进行评估。基于此,我可以解决问题:
#define PRIVATE_CONCAT(a, b) a ## b
#define CONCAT(a, b) PRIVATE_CONCAT(a, b)
#define GET_100TH( \
_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, _63, _64, _65, _66, _67, _68, _69, _70, \
_71, _72, _73, _74, _75, _76, _77, _78, _79, _80, \
_81, _82, _83, _84, _85, _86, _87, _88, _89, _90, \
_91, _92, _93, _94, _95, _96, _97, _98, _99, PAR, \
...) PAR
#define HAS_PARAMETER(...) GET_100TH(placeholder, ##__VA_ARGS__, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 0)
#define FIRST_PARAMETER_WITH_PREPENDED_COMMA0(...)
#define FIRST_PARAMETER_WITH_PREPENDED_COMMA1(a, ...) , a
#define FIRST_PARAMETER_WITH_PREPENDED_COMMA(...) CONCAT(FIRST_PARAMETER_WITH_PREPENDED_COMMA, HAS_PARAMETER(__VA_ARGS__))(__VA_ARGS__)
#define FOO(a, ...) if (a) foo(a FIRST_PARAMETER_WITH_PREPENDED_COMMA(__VA_ARGS__))
基于此,我可以解决这个问题:
#define PRIVATE_CONCAT(a, b) a ## b
#define CONCAT(a, b) PRIVATE_CONCAT(a, b)
#define GET_100TH( \
_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, _63, _64, _65, _66, _67, _68, _69, _70, \
_71, _72, _73, _74, _75, _76, _77, _78, _79, _80, \
_81, _82, _83, _84, _85, _86, _87, _88, _89, _90, \
_91, _92, _93, _94, _95, _96, _97, _98, _99, PAR, \
...) PAR
#define HAS_PARAMETER(...) GET_100TH(placeholder, ##__VA_ARGS__, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 0)
#define FIRST_PARAMETER_WITH_PREPENDED_COMMA0(...)
#define FIRST_PARAMETER_WITH_PREPENDED_COMMA1(a, ...) , a
#define FIRST_PARAMETER_WITH_PREPENDED_COMMA(...) CONCAT(FIRST_PARAMETER_WITH_PREPENDED_COMMA, HAS_PARAMETER(__VA_ARGS__))(__VA_ARGS__)
#define FOO(a, ...) if (a) foo(a FIRST_PARAMETER_WITH_PREPENDED_COMMA(__VA_ARGS__))
我提出了一个带有通用lambda的可变宏作为解决方案。 要点如下:
- 很难将
和a
作为宏中的传递参数传递给lambda,因为当\uuuuu-VA\u-ARGS\uuuu
为空时\uu-VA\u-ARGS\uu
变成[](){...}(a, __VA_ARGS__)
而这[](){...}(a,)
导致编译错误。 因此,我们将,
的第一个和第二个参数分别拆分为捕获的参数和传递的参数,如下所示。 然后,我们可以在宏中使用通用lambda,即使FOO
为空\uu VA\u ARGS\uu
[a](){...}(__VA_ARGS__)
的大小可以在编译时作为
进行计算。然后我们可以使用constexpr auto N
来分隔函数调用if constexpr
- 我们还可以应用带有初始值设定项的if语句,该初始值设定项是从C++17引入的,用于
if(a)
#包括
#定义FOO(a,…)\
如果(常数布尔a=(a);a)\
[a](自动&&…参数)\
{ \
const auto t=std::make_tuple(std::forward(args)…)\
constexpr auto N=std::tuple\u size::value\
\
如果constexpr(N==0){\
返回foo(a_)\
} \
否则{\
返回foo(a_,std::get(t))\
} \
}(uu VA_uargs_uu)
我建议使用一个带有通用lambda的可变宏作为解决方案。
要点如下:
- 很难将
和a
作为宏中的传递参数传递给lambda,因为当\uuuuu-VA\u-ARGS\uuuu
为空时\uu-VA\u-ARGS\uu
变成[](){...}(a, __VA_ARGS__)
而这[](){...}(a,)
导致编译错误。 因此,我们将,
的第一个和第二个参数分别拆分为捕获的参数和传递的参数,如下所示。 然后,我们可以在宏中使用通用lambda,即使FOO
为空\uu VA\u ARGS\uu
[a](){...}(__VA_ARGS__)
的大小可以在编译时作为
进行计算。然后我们可以使用constexpr auto N
来分隔函数调用if constexpr
- 我们还可以应用带有初始值设定项的if语句,该初始值设定项是从C++17引入的,用于
if(a)
#包括
#定义FOO(a,…)\
如果(常数布尔a=(a);a)\
[a](自动&&…参数)\
{ \
const auto t=std::make_tuple(std::forward(args)…)\
constexpr auto N=std::tuple\u size::value\
\
如果constexpr(N==0){\
返回foo(a_)\
} \
否则{\
返回foo(a_,std::get(t))\
} \
}(uu VA_uargs_uu)
可能重复@Frank:谢谢你发现这个问题,基于此,我可以解决这个问题。你真的需要宏吗?简单重载似乎可以完成这项工作。@Jarod42:是的,需要宏,因为我需要懒洋洋地计算FOO的参数(我的意思是,在实际代码中,当某些条件为true时,我只调用FOO
。如果该条件为false,则不调用FOO
,也不计算其参数)。@geza是a
的类型,b
和
都一样吗?可能重复@Frank:谢谢你发现这个问题,基于此我可以解决这个问题。你真的需要宏吗?简单重载似乎可以完成这项工作。@Jarod42:是的,需要宏,因为我需要惰性地计算FOO的参数(我的意思是,在实际代码中,我只调用FOO
,w