C++宏创建一个字符串数组

One*_*ros 5 c++ preprocessor

有没有办法用预处理器宏创建std::string(或char*)数组?

像这样的东西:

std::string myStrings[] = {MAGIC_MACRO(a, b, c)};
Run Code Online (Sandbox Code Playgroud)

结果:

std::string myStrings[] = {"a", "b", "c"}
Run Code Online (Sandbox Code Playgroud)

我知道它看起来毫无意义但我需要它在一个更复杂的宏中,它具有可变数量的参数

And*_*ing 5

下面的代码可以满足您所要求的最多 1024 个参数,并且无需使用 boost 等其他内容。它定义了一个EVAL(...)MAP(m, first, ...)来执行递归,并在每次迭代时使用m带有下一个参数的宏first

使用它,你的MAGIC_MACRO(...)看起来像:#define MAGIC_MACRO(...) EVAL(MAP(STRINGIZE, __VA_ARGS__))

它主要是从C Pre-Processor Magic复制而来。那里的解释也很好。您还可以像EVAL(...)在这个git 存储库一样下载这些帮助器宏,实际代码中也有很多解释。它是可变的,因此它需要您想要的参数数量。

但我更改了FIRSTSECOND宏,因为它使用 Gnu 扩展,就像我从中复制的源中一样。

主要功能部分:

int main()
{
   std::string myStrings[] = { MAGIC_MACRO(a, b, c) }; // Expands to: std::string myStrings[] = { "a" , "b" , "c" };
   std::string myStrings[] = { MAGIC_MACRO(a, b, c, x, y, z) }; // Expands to: std::string myStrings[] = { "a" , "b" , "c", "x" , "y" , "z" };
}
Run Code Online (Sandbox Code Playgroud)

宏定义:

#define FIRST_(a, ...) a
#define SECOND_(a, b, ...) b

#define FIRST(...) FIRST_(__VA_ARGS__,)
#define SECOND(...) SECOND_(__VA_ARGS__,)

#define EMPTY()

#define EVAL(...) EVAL1024(__VA_ARGS__)
#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
#define EVAL1(...) __VA_ARGS__

#define DEFER1(m) m EMPTY()
#define DEFER2(m) m EMPTY EMPTY()()

#define IS_PROBE(...) SECOND(__VA_ARGS__, 0)
#define PROBE() ~, 1

#define CAT(a,b) a ## b

#define NOT(x) IS_PROBE(CAT(_NOT_, x))
#define _NOT_0 PROBE()

#define BOOL(x) NOT(NOT(x))

#define IF_ELSE(condition) _IF_ELSE(BOOL(condition))
#define _IF_ELSE(condition) CAT(_IF_, condition)

#define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
#define _IF_0(...)             _IF_0_ELSE

#define _IF_1_ELSE(...)
#define _IF_0_ELSE(...) __VA_ARGS__

#define COMMA ,

#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
#define _END_OF_ARGUMENTS_() 0

#define MAP(m, first, ...)           \
  m(first)                           \
  IF_ELSE(HAS_ARGS(__VA_ARGS__))(    \
    COMMA DEFER2(_MAP)()(m, __VA_ARGS__)   \
  )(                                 \
    /* Do nothing, just terminate */ \
  )
#define _MAP() MAP

#define STRINGIZE(x) #x
#define MAGIC_MACRO(...) EVAL(MAP(STRINGIZE, __VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)