Препроцессор VC++ vs GCC
короче говоря, препроцессоры gcc и vc++ имеют разные выходные данные с одним и тем же входом. Похоже, что вариадические макросы в vc++ не делают "сопоставления аргументов" (если это правильный термин), если они переданы другим макросам. Например:
#define MACRO(a, ...) head:a, tail:MACRO_OTHER(__VA_ARGS__)
#define MACRO_OTHER(a, ...) head:a, tail:__VA_ARGS__
С
MACRO(1, 2, 3, 4, 5)
выход gcc:
head:1, tail:head:2, tail:3,4,5
на VC++ выход:
head:1, tail:head:2,3,4,5, tail:
видимо a
на MACRO_OTHER
и 2,3,4,5
С пустым разделом variadic arguments.
Имея это в виду, есть ли способ создания альтернативы vc++ для следующего макроса (который отлично работает с gcc)
#define VA_TYPES_WITH_ARGS(...) __VA_TYPES_WITH_ARGS(VA_NUM_ARGS(__VA_ARGS__),##__VA_ARGS__)
#define __VA_TYPES_WITH_ARGS(n, ...) _VA_TYPES_WITH_ARGS(n,##__VA_ARGS__)
#define _VA_TYPES_WITH_ARGS(n, ...) _VA_TYPES_WITH_ARGS_##n(__VA_ARGS__)
#define _VA_TYPES_WITH_ARGS_0()
#define _VA_TYPES_WITH_ARGS_1(type ) type _arg1
#define _VA_TYPES_WITH_ARGS_2(type, ...) type _arg2, _VA_TYPES_WITH_ARGS_1(__VA_ARGS__)
#define _VA_TYPES_WITH_ARGS_3(type, ...) type _arg3, _VA_TYPES_WITH_ARGS_2(__VA_ARGS__)
// etc
он в основном добавляет _argK
для каждого аргумента.
пример:
VA_TYPES_WITH_ARGS(int, bool, float)
будет расширяться, чтобы
int _arg3, bool _arg2, float _arg1
любая помощь будет высоко оценили.
вопросы, связанные с препроцессора:
2 ответов
вы можете сделать это разумно кросс-компилятором (и принять еще много аргументов без дополнительной работы для загрузки), используя Boost, который, я могу сказать вам, потратив столько времени на просмотр заголовков, имеет много обходных путей для таких проблем, как эти:
#define VA_TYPES_WITH_ARGS(...) \
BOOST_PP_ENUM( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
VA_TYPES_WITH_ARGS_MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
)
#define VA_TYPES_WITH_ARGS_MACRO(z, n, data) \
BOOST_PP_TUPLE_ELEM(n, data) BOOST_PP_CAT( \
_arg, \
BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(data), n) \
)
VA_TYPES_WITH_ARGS(int, bool, float) //int _arg3 , bool _arg2 , float _arg1
первый макрос перебирает (ENUM
) над аргументами variadic, вызывая второй для каждого и добавляя запятые соединения. Он формирует кортеж из вариационных данных, чтобы дать второму макрос.
второй формирует этот элемент (TUPLE_ELEM
), затем _arg
объедены (CAT
) С size - n
(SUB
), где size
- количество элементов в данных вариативную (с учетом макрос как кортеж) (TUPLE_SIZE
).
автономный подход, который работает для VC++ и разрывается с GCC, является:
#define EXPAND(...) __VA_ARGS__
#define LPAREN (
#define RPAREN )
теперь вместо использования макроса, как x(__VA_ARGS__)
, используйте его так:EXPAND(x LPAREN __VA_ARGS__ RPAREN)
.
это заставляет препроцессор VC++ сканировать аргументы позже, чем обычно.
вы должны быть в состоянии объединить две формы, чтобы поместить биты компилятора в одном месте.
обратите внимание, что там не может быть стандартным ответом на C++: вы полагаетесь на x()
будучи вызовом макроса без аргументов. Это не так, как препроцессор работает в стандартном C++: if x
- это вариативная макрос x()
вызывает макрос с одним аргументом, и что единственный аргумент пуст. Кроме того, вы полагаетесь на возможность опустить переменные аргументы: стандартный C++ также не позволяет этого. Если макрос определен как #define FOO(x,...)
, ссылаясь на него как FOO(1)
является недействительным. Как не может быть стандартного подхода, надеюсь это не проблема для вас, что различные подходы обязательно будут специфичны для компилятора.