如何在C ++中使用宏生成任意长的参数列表?

时间:2014-07-11 01:36:05

标签: c++ macros

我想要一个宏,它接受任意数量的参数,将每一对拼接在一起,在末尾添加一些名称,让我们说Type,然后将它们作为模板参数传递给某些类型,我们称之为CompileTimeList。所以我会给它这样的东西:

MACRO( \
  First,Set, \
  Second,Type, \
  Third,Thing)

它将扩展为:

CompileTimeList<
  FirstSetType,
  SecondTypeType,
  ThirdThingType>

天真的解决方案是一个可变的递归模板,这是不允许的:

Can we have recursive macros?

我可以使用这种方法手动破解宏:

Macro recursive expansion to a sequence

但它将限于我定义的许多参数。我希望能够扩展任何长度的参数。这在C ++ 11中是否可行?我也有可用的Boost 1.55,在其他问题中没有提及。

为了尝试实现克里斯&#39;回答,我写了以下程序:

  1 #include <boost/preprocessor.hpp>
  2
  3 #include <vector>
  4 #include <algorithm>
  5
  6 #define MACRO(...)  \
  7     std::find( \
  8     BOOST_PP_ENUM( \
  9         BOOST_PP_DIV(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 2), \
 10         ENUM_MACRO, \
 11         BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
 12     ) \
 13     )
 14
 15 #define ENUM_MACRO(z, n, data) \
 16     BOOST_PP_CAT( \
 17         BOOST_PP_CAT( \
 18             BOOST_PP_TUPLE_ELEM(BOOST_PP_MUL(n, 2), data), \
 19             BOOST_PP_TUPLE_ELEM(BOOST_PP_INC(BOOST_PP_MUL(n, 2)), data) \
 20         ), \
 21         Type \
 22     )
 23
 24
 25 typedef int FirstNameType;
 26 typedef std::vector<int>::iterator SecondNameType;
 27 typedef std::vector<int>::iterator ThirdNameType;
 28
 29 int main()
 30 {
 31     std::vector<int>();
 32     auto it = MACRO(First, Name, Second, Name, Third, Name);
 33     return 0;
 34 }

从使用逗号开始产生大量错误:

  

test.cpp:在函数'int main()'中:   src / boost / boost / preprocessor / punctuation / comma.hpp:19:27:错误:   在','标记#define之前预期的primary-expression   BOOST_PP_COMMA(),

1 个答案:

答案 0 :(得分:1)

您可以通过Boost使用几个宏来实现所需的语法:

#define BOOST_PP_VARIADICS
#include <boost/preprocessor.hpp>

//The main part is BOOST_PP_ENUM, which loops the number of arguments / 2 times.
//Each loop, ENUM_MACRO is called with the index and a tuple containing the arguments.
//A comma is inserted between all expansions of ENUM_MACRO.
#define MACRO(...)  \
    CompileTimeList< \
    BOOST_PP_ENUM( \
        BOOST_PP_DIV(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 2), \
        ENUM_MACRO, \
        BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
    ) \
    >

//Since it's called #args/2 times, we multiply the index by 2.
//All it does is concatenate the first in its pair with the second, and then to Type.
#define ENUM_MACRO(z, n, data) \
    BOOST_PP_CAT( \
        BOOST_PP_CAT( \
            BOOST_PP_TUPLE_ELEM(BOOST_PP_MUL(n, 2), data), \
            BOOST_PP_TUPLE_ELEM(BOOST_PP_INC(BOOST_PP_MUL(n, 2)), data) \
        ), \
        Type \
    )


MACRO(a, b, c, d) //CompileTimeList< abType , cdType >

See it work here.

当处于当前状态时,此宏将简单地忽略奇数列表中的最后一个参数,可能会产生一个带有简单static_assert的错误,或者对最后一个参数执行一些特殊操作。如此渴望。