Visual Studio宏__VA_ARGS__未正确解压缩

时间:2016-03-22 13:29:55

标签: c++ visual-studio macros

我在一个项目上工作,我需要模拟一个递归宏(这里是TEST_COLUMN)。但它在视觉2013上失败了。 在gcc上,它工作正常,但有了视觉,我有一个错误。 所以,要调试这个宏,我使用static_assert(也许有更好的方法)。 每次,在宏TEST_COLUMN_X(name,...)中,name的值包含所有参数,而不仅仅是第一个参数。

如果有人有想法解决这个问题。 以下是重现它所需的最少代码:

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x) //transform x to char

#define EXPAND(x) x
#define NUM_ARGS_HELPER(X,X64,X63,X62,X61,X60,X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N
//count to number of argument containing 
#define NUM_ARGS(...) EXPAND(NUM_ARGS_HELPER(0, __VA_ARGS__ ,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) in __VA_ARGS__

//define each level of the macro
#define TEST_COLUMN_0            ;
#define TEST_COLUMN_1(name)      static_assert(false,"TEST_COLUMN_1 " STR(name));
#define TEST_COLUMN_2(name,...)  static_assert(false,"TEST_COLUMN_2 " STR(name)); //TEST_COLUMN_1(__VA_ARGS__)
#define TEST_COLUMN_3(name,...)  static_assert(false,"TEST_COLUMN_3 " STR(name)); //TEST_COLUMN_2(__VA_ARGS__)
#define TEST_COLUMN_4(name,...)  static_assert(false,"TEST_COLUMN_4 " STR(name)); TEST_COLUMN_3(__VA_ARGS__)

//tricks to call the correct macro (TEST_COLUMN_X)
#define TEST_COLUMN_N1(N,...) TEST_COLUMN_##N(__VA_ARGS__)
#define TEST_COLUMN(N,...) TEST_COLUMN_N1(N,__VA_ARGS__)

//recursive macro
#define TEST_STATIC_COLUMN(...) TEST_COLUMN(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)

int main(int argc, char* argv[])
{
    TEST_STATIC_COLUMN(a, b, c);
    return 0;
}

输出:

main.cpp(21): error C2338: TEST_COLUMN_3 a, b, c

但它应该是

    main.cpp(21): error C2338: TEST_COLUMN_3 a

您可以使用在线编译器http://webcompiler.cloudapp.net/

对此进行测试

1 个答案:

答案 0 :(得分:0)

我不知道为什么,但是给EXPAND添加了一些电话来解决这个问题:

#define TEST_COLUMN_2(name,...)  static_assert(false,"TEST_COLUMN_2 " STR(name)); EXPAND(TEST_COLUMN_1(__VA_ARGS__))
#define TEST_COLUMN_3(name,...)  static_assert(false,"TEST_COLUMN_3 " STR(name)); EXPAND(TEST_COLUMN_2(__VA_ARGS__))
#define TEST_COLUMN_4(name,...)  static_assert(false,"TEST_COLUMN_4 " STR(name)); EXPAND(TEST_COLUMN_3(__VA_ARGS__))
#define TEST_COLUMN_N1(N,...) EXPAND(TEST_COLUMN_##N(__VA_ARGS__))