删除宏扩展的尾随逗号

Remove trailing comma of macro expansion

我有一个 'system' 可以使用宏生成 类(不幸的是没有其他方法)。

在某些情况下,例如对于初始化列表,这会导致尾随逗号 我想摆脱:

#define REMOVE_TRAILING_COMMA(...) ?what to put here?
#define FOO a, b, c, d, e, f, g, h,

REMOVE_TRAILING_COMMA(FOO) --> expands to a, b, c, d, e, f, g, h

当然,如果它只是删除最后一个参数也可以。 如果 REMOVE_TRAILING_COMMA(a, b, c) 扩展为 a, b

宏总是至少有两个参数,所以最小的情况 将是:REMOVE_TRAILING_COMMA(a,) --> 扩展为 a.

这可能吗?我用 Google 搜索了几个小时,但是 什么都没有。

我很乐意使用 #define REMOVE_FIRST(a, ...) __VA_ARGS__,但这需要颠倒宏参数的顺序。我看不出有什么方法可以做到这一点(除了重载它之外)。因此,根据参数数量重载宏并枚举每个重载以删除尾随参数:

// example macro overoad for up to 9 args
// TODO: write REMOVE_TRAILING_COMMA_{1,2,3,4,5....} for each case
#define REMOVE_TRAILING_COMMA_8(_1,_2,_3,_4,_5,_6,_7,_8)  \
                                _1,_2,_3,_4,_5,_6,_7
#define REMOVE_TRAILING_COMMA_9(_1,_2,_3,_4,_5,_6,_7,_8,_9)  \
                                _1,_2,_3,_4,_5,_6,_7,_8
#define REMOVE_TRAILING_COMMA_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...)  \
        REMOVE_TRAILING_COMMA_##N
#define REMOVE_TRAILING_COMMA(...)  \
        REMOVE_TRAILING_COMMA_N(__VA_ARGS__,9,8,7,6,5,4,3,2,1)(__VA_ARGS__)

#define FOO a, b, c, d, e, f, g, h,

REMOVE_TRAILING_COMMA(FOO) --> expands to a, b, c, d, e, f, g, h

Carlo Wood 添加了以下内容:

谢谢!我写了一个小程序来生成上面的内容,所以它是 很容易增加仍然适用的最大参数数量:

#include <string>
#include <iostream>
#include <sstream>

std::string args1_N(int n)
{
  std::ostringstream ss;
  char const* prefix = "_";
  for (int a = 1; a <= n; ++a)
  {
    ss << prefix << a;
    prefix = ",_";
  }
  return ss.str();
}

int main()
{
  int const max_args = 9;

  for (int n = 1; n <= max_args + 1; ++n)
    std::cout << "#define REMOVE_TRAILING_COMMA_" << n << "(" << args1_N(n) <<
      ") \\n                                " << args1_N(n - 1) << std::endl;
  std::cout << "#define REMOVE_TRAILING_COMMA_N(" << args1_N(max_args + 1) << ",N,...) \\n" <<
    "        REMOVE_TRAILING_COMMA_##N\n";
  std::cout << "#define REMOVE_TRAILING_COMMA(...) \\n" <<
    "        REMOVE_TRAILING_COMMA_N(__VA_ARGS__";
  for (int a = max_args + 1; a > 0; --a)
    std::cout << "," << a;
  std::cout << ")(__VA_ARGS__)" << std::endl;
}