【问题标题】:C Preprocessor, Macro "Overloading"C 预处理器,宏“重载”
【发布时间】:2011-03-26 03:05:49
【问题描述】:

我正在尝试执行某种宏“重载”,以便 MACRO(something) 的扩展方式与 MACRO(something, else) 不同。

使用我从here 获得的 sn-p(我不确定它是否 100% 可移植)和 Boost PP 库中的一些函数,我能够使其工作:D

//THESE TWO COUNT THE NUMBER OF ARGUMENTS
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)

//THIS ONE RETURNS THE PARAMETER AT POSITION _i FROM A LIST OF __VA_ARGS__
#define VA_ARG(_i, ...) BOOST_PP_ARRAY_ELEM(_i, (VA_NARGS(__VA_ARGS__), (__VA_ARGS__)))

//AND THIS ONE IS THE 'OVERLOADED' MACRO ;)
#define TEST(...) BOOST_PP_IF(BOOST_PP_EQUAL(1, VA_NARGS(__VA_ARGS__)), function_A(VA_ARG(0, __VA_ARGS__)), \ //1 parameter
                  BOOST_PP_IF(BOOST_PP_EQUAL(2, VA_NARGS(__VA_ARGS__)), function_B(VA_ARG(0, __VA_ARGS__) + VA_ARG(1, __VA_ARGS__)), \ //2 parameters
                  BOOST_PP_IF(BOOST_PP_EQUAL(3, VA_NARGS(__VA_ARGS__)), function_C(VA_ARG(1, __VA_ARGS__) + VA_ARG(2, __VA_ARGS__)), BOOST_PP_EMPTY())) // 3 parameters and so on ...

So       TEST(a) = function_A(a)
      TEST(a, b) = function_B(a + b)
   TEST(a, b, c) = function_C(b + c)

现在我仍然想念另外两件我想做的事情:

  1. (这个我真的不在乎我是否从未解决它)我相信可以编写一个宏,当占用“变体”的数量时,其对应的“输出”会生成类似的代码上面那个。像 TEMPLATE(3, function_A(...), function_B(...), function_C(...)) 这样的东西来生成上面的例子。

  2. 在没有参数的情况下调用 TEST() 会发生什么?好吧,VA_NARGS 展开为 1。但第一个参数是“”(无)。我试图找到一种方法来检测__VA_ARGS__ 中的“零”参数或区分“空”参数和真实参数,以便扩展“重载”功能以应对这种情况。有什么想法吗?

【问题讨论】:

  • Boost -> C++ -> 如果你已经在使用 C++,不要乱用预处理器,使用普通函数(如果你愿意,可以内联)。 C 预处理器故意是愚蠢的,这样人们就不会滥用它。
  • 这是针对 C 还是 C++ 的?另请注意,将可变参数与宏一起使用是不可移植的。
  • @Paul R:可变参数宏是 C99 的一部分。
  • @Jens:感谢您指出这一点-尽管如果您想定位例如,它们仍然不可移植。 MSVC,因为微软仍然不支持 C99。
  • @保罗。 MSVC 不支持 C99,但他们支持 __VA_ARG____VA_ARG__, (2008 express)

标签: macros c-preprocessor variadic-macros boost-preprocessor


【解决方案1】:

首先回答您的问题 2。是的,使用可变参数宏也可以检测空参数列表。解释有点长,我写了here。将这种方法与您正在使用的 boost 宏结合起来应该相对容易。

对于您的问题 1,是的,这也是可能的。我认为 Boost 有一些迭代器宏接近于此,但它们看起来有点可怕。如果我理解正确,您必须使用嵌套列表(a, (b, (c,d))) 之类的东西,不太方便。

(我写了一组可以更直接实现这个的宏, 但不幸的是,该软件包尚未准备好发布。如果您真的对此感兴趣,请私下联系我。)

编辑:P99 包同时发布,其中包含很多关于宏“重载”和类型通用宏的内容。

【讨论】:

  • Boost 迭代器宏有几种不同类型的序列:列表(a (b (c,d) ) )、元组(a,b,c)(必须知道长度)和列表(a)(b)(c)。后者对我来说是最容易处理的。
猜你喜欢
  • 2020-02-09
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 2016-12-14
  • 2018-01-04
相关资源
最近更新 更多