3

我试图通过参数的数量来重载宏。
当然,我实际上不能重载宏。

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

#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__将为空,并且应该已删除昏迷,因此将选择并使用TEST2 。

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

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

4

2 回答 2

3

基于这个答案

#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;
}
于 2012-08-15T17:48:08.540 回答
1

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

那么你没有正确使用它:你需要##在昏迷和__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();
}
于 2012-08-15T18:01:40.713 回答