【问题标题】:Remove trailing comma of macro expansion删除宏扩展的尾随逗号
【发布时间】:2021-05-16 21:10:32
【问题描述】:

我有一个使用宏生成类的“系统”(遗憾的是没有其他方法)。

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

#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

这甚至可能吗?我用谷歌搜索了几个小时,但是 什么都没有发生。

【问题讨论】:

  • 这是一个需要在生成器中解决的问题,而不是对生成的代码进行更正。
  • 也许this 有帮助...我还没有尝试为您的问题编写解决方案。
  • 为什么 FOO 会以这种形式存在?
  • 很高兴我能帮上忙 :-)

标签: c++ c gcc preprocessor


【解决方案1】:

我会很高兴使用#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;
}

【讨论】:

  • 谢谢 - 同时我正在使用 pmg 的链接编写自己的解决方案并制作了 github.com/CarloWood/ai-utils/blob/master/macro_args.h 似乎使用相同的想法,不是吗?
  • eems to use the same idea
  • 不知道为什么要介绍REMOVE_TRAILING_COMMA_IN?当我只做REMOVE_TRAILING_COMMA_IN(FOO) 时,它似乎也有效
  • 哦,对,它会起作用,因为REMOVE_TRAILING_COMMA_N 做了另一个级别的扩展来扩展参数。我相信只是约定,在调用 internal 之前让宏参数完全展开,但实际上它可以被删除。
  • 您也可以使用boost.org/doc/libs/1_75_0/libs/preprocessor/doc/index.html BOOST_PP_TUPLE_REVERSE 然后使用#define REMOVE_FIRST(a, ...) __VA_ARGS__。或者从 P99 我看到 P99_ALLBUTLAST
猜你喜欢
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-13
  • 2022-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多