Каковы различия между препроцессорами GCC / CLANG против MSVC? - PullRequest
0 голосов
/ 05 ноября 2018

Следующие макросы препроцессора (обычные подозрения: тестирование на пустом списке аргументов и подсчет количества аргументов) выполняются без предупреждений в 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, который не ведет себя правильно?

1 Ответ

0 голосов
/ 05 ноября 2018

Препроцессор Microsoft Visual C ++ обнаружил соответствие проблем.

Они переписали препроцессор, но старый включен по умолчанию. Чтобы включить, мы надеемся, более совместимую, выберите эту опцию:

/ экспериментальный: препроцессор

Начиная с версии Visual Studio 2017 15.8 Preview 3.

Я запустил макросы, используя параметр: /experimental:preprocessor в последней выпущенной версии 15.8.9 со следующими результатами:

: 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.

...