以下预处理器宏(通常的怀疑:在空参数列表上进行测试并计算参数数量)在gcc / clang上运行时没有警告,但在Microsoft VisualC上失败:
// IS_EMPTY() returns nothing if the parameter list is empty and a single ',' (comma) otherwise.
// The parameter list can have up to 32 parameters
#define IS_EMPTY(...) IS_EMPTY1(__VA_ARGS__)
#define IS_EMPTY1(...) IS_EMPTY2(DROP_PARAMS __VA_ARGS__ (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,EMPTY))
#define IS_EMPTY2(...) IS_EMPTY3(__VA_ARGS__)
#define IS_EMPTY3(f,...) TEST_EMPTY_##f )
#define DROP(...)
#define DROP_PARAMS(...) DROP_PARAMS1(__VA_ARGS__,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
#define DROP_PARAMS1(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,__m,...) CATCH_##__m
#define TEST_EMPTY_DROP_PARAMS , DROP(
#define TEST_EMPTY_CATCH_EMPTY DROP(
#define TEST_EMPTY_CATCH_ , DROP(
//--- testcode below ---
#define TEST_EMPTY(...) __VA_ARGS__ : TAKE_2ND(IS_EMPTY(__VA_ARGS__) not,) empty
#define TAKE_2ND(...) TAKE_2ND_(__VA_ARGS__,,)
#define TAKE_2ND_(f,s,...) s
TEST_EMPTY()
TEST_EMPTY(a.b.)
TEST_EMPTY(A)
TEST_EMPTY(())
TEST_EMPTY(int()(more))
TEST_EMPTY((int))
TEST_EMPTY(foo bar)
TEST_EMPTY(*)
#define FOO(x) x
#define BAR
TEST_EMPTY(FOO(BAR))
TEST_EMPTY(1,2)
TEST_EMPTY(1.)
TEST_EMPTY(.1)
TEST_EMPTY(1,)
TEST_EMPTY((int)(float))
TEST_EMPTY(() this)
TEST_EMPTY(() is, () not () empty ())
TEST_EMPTY(,notempty)
TEST_EMPTY((),notempty)
TEST_EMPTY((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,))
在clang和gcc上的输出:
: empty
a.b. : not empty
A : not empty
() : not empty
int()(more) : not empty
(int) : not empty
foo bar : not empty
* : not empty
: empty
1,2 : not empty
1. : not empty
.1 : not empty
1, : not empty
(int)(float) : not empty
() this : not empty
() is, () not () empty () : not empty
,notempty : not empty
(),notempty : not empty
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,) : not empty
在MSVC上的输出:
: empty
a.b. : empty
A : empty
() : empty
int()(more) : empty
(int) : empty
foo bar : empty
* : empty
: empty
1,2 : empty
1. : empty
.1 : empty
1, : empty
(int)(float) : empty
() this : empty
() is, () not () empty () : empty
,notempty : empty
(),notempty : empty
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,) : empty
由于MSVC完全保持沉默,我想知道我的解决方案还有多远。还是MSVC行为不正确?
答案 0 :(得分:2)
Microsoft的Visual C ++预处理器存在compliance个问题。
他们已经重写了预处理器,但是默认情况下启用了旧的预处理器。要启用合规性更高的选项,请选择此选项:
/ experimental:preprocessor
从Visual Studio 2017 15.8 Preview 3版本开始。
我在最新发布的版本15.8.9上使用选项/experimental:preprocessor
运行了宏,结果如下:
: empty
a.b. : not empty
A : not empty
() : not empty
int()(more) : not empty
(int) : not empty
foo bar : not empty
* : not empty
: empty
1, 2 : not empty
1. : not empty
.1 : not empty
1, : not empty
(int)(float) : not empty
() this : not empty
() is, () not () empty() : not empty
, notempty : not empty
(), notempty : not empty
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ) : not empty
错误的“空”现在为“非空”,并且与GCC和Clang的预处理器一致。