c++ - 提取 __VA_ARGS__ 的第一个参数

标签 c++ c++17

假设我有一个宏:

#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)

那么建议的宏如下。 这也适用于您。

DEMO

#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/

相关文章:

c++ - 将 std::vector 对象用于 DSP 应用程序会不会效率低下?

c++ - 使用cmake创建UWP软件包

c++ - 可变参数,它们都是模板类型的特化

c++ - 好友声明的反面

c++ - 在派生类中重载模板运算符

c++ - VCL 或 MFC 可以在我的应用程序中免费使用吗?

c++ - Windows 上的 Clang/LLVM 6.0.0 不需要静态数据成员声明的定义

c++ - std::any 用于不能复制构造的对象

c++ - 为什么在这些折叠表达式中使用 std::min 是未定义的行为?

c++ - Eigen 和 CImg 兼容性问题