【问题标题】:Overloading a macro重载宏
【发布时间】:2012-08-12 00:51:15
【问题描述】:

我正在尝试按参数数量重载宏。
当然,我实际上不能重载宏。

我尝试使用可变参数宏来选择正确的宏(使用这样一个事实,即如果 __VA_ARGS__ 不存在,它应该删除它之前的最后一个逗号 - GCC Reference):

#define TEST1() printf("TEST1");
#define TEST2() printf("TEST2");

#define CHOOSER(x, y,FUNC,...) FUNC()

#define MANIMACRO(...) CHOOSER(,__VA_ARGS__,TEST1,TEST2)

int main(void)
{
    MANIMACRO(1);
    MANIMACRO();
}

这个想法是,如果__VA_ARGS__ 存在,它应该将 4 个参数传递给 CHOOSER,其中第三个参数应该与未使用的参数一起“消失”。所以会选择 TEST1。

如果没有参数,__VA_ARGS__ 将为 null,并且应该已删除逗号,因此将选择并使用 TEST2

所以,我想这不起作用,因为 __VA_ARGS__ 可能仅在预处理阶段结束时才被删除,在整个事情已经展开之后。

那么,我该怎么做呢? (在 vs2010 中)

【问题讨论】:

标签: c++ visual-studio-2010 macros c-preprocessor variadic-macros


【解决方案1】:

基于this answer:

#define TEST1(expr)           printf("test1")
#define TEST2(expr, explain)  printf("test2")

#define N_ARGS_IMPL2(_1, _2, count, ...) \
   count
#define N_ARGS_IMPL(args) \
   N_ARGS_IMPL2 args
#define N_ARGS(...) N_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
 /* Pick the right helper macro to invoke. */
#define CHOOSER2(count) TEST##count
#define CHOOSER1(count) CHOOSER2(count)
#define CHOOSER(count)  CHOOSER1(count)
 /* The actual macro. */
#define TEST_GLUE(x, y) x y
#define TEST(...) \
   TEST_GLUE(CHOOSER(N_ARGS(__VA_ARGS__)), \
               (__VA_ARGS__))

int main() {
  TEST(one); // singleArgumentExpansion(one)
  TEST(two, "foopy"); // twoArgumentExpansion(two, "foopy")
  return 0;
}

【讨论】:

  • 在 VS2010 中这也只返回 TEST1 两次
  • @YochaiTimmer,这个答案 (stackoverflow.com/a/9338429/390913) 提出了一种解决方法。
  • 链接中的示例效果很好。更新你的答案,否则我会稍后再做。
【解决方案2】:

首先,您链接的页面说明它是 GCC 扩展。如果您使用的是标签所暗示的 Visual Studio 2010,我并不惊讶它不起作用。

那么你没有正确使用它:你需要在 coma 和 __VA_ARGS__ 之间使用 ##。如果我这样做并修复使两个 TESTx 宏都打印 TEST1 的错字,我会得到 gcc 4.4 所期望的行为

#include <stdio.h>

#define TEST1() printf("TEST1\n");
#define TEST2() printf("TEST2\n");

#define CHOOSER(x, y, FUNC,...) FUNC()

#define MANIMACRO(...) CHOOSER(,##__VA_ARGS__,TEST1,TEST2)

int main(void)
{
    MANIMACRO(1);
    MANIMACRO();
}

【讨论】:

  • 再说一次,对于 VS2010 不提供 GCC 扩展,我并不感到惊讶。
猜你喜欢
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 2013-01-20
  • 2014-10-30
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多