Перегрузка макроса препроцессора C/С++ по структуре его аргумента
Я хотел бы написать макрос препроцессора, который делает одно, если этот аргумент представляет собой скопированный токены токенов, например:
MY_MACRO((x, y))
и что-то еще, если это всего лишь один токен, например:
MY_MACRO(x)
Возможно ли это?
Как насчет различия между количеством разделенных пространством токенов, то есть между MY_MACRO(x)
и MY_MACRO(x y)
?
Обратите внимание, что я не пытаюсь перегрузить на основе количества аргументов - во всех случаях это унарный макрос.
EDIT: я готов использовать переменные макросы, если они помогают
Ответы
Ответ 1
Что касается вашего первого вопроса, следующие макросы могут соответствовать вашей цели:
#define CONCAT_( x, y ) x ## y
#define CONCAT( x, y ) CONCAT_( x, y )
#define IS_SINGLE_1(...) 0
#define IGNORE(...)
#define IS_SINGLE_2_0 0 IGNORE(
#define IS_SINGLE_2_IS_SINGLE_1 1 IGNORE(
#define IS_SINGLE( x ) CONCAT( IS_SINGLE_2_, IS_SINGLE_1 x ) )
IS_SINGLE((x, y)) // 0
IS_SINGLE(x) // 1
Макрос IS_SINGLE
расширяется до 1, если аргумент является единственным токеном,
в противном случае 0.
Надеюсь, что это поможет
Ответ 2
Использование boost.preprocessor
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define SEQ (w)(x)(y)(z)
#define MACRO(r, data, elem) BOOST_PP_CAT(elem, data)
BOOST_PP_SEQ_FOR_EACH(MACRO, _, SEQ) // expands to w_ x_ y_ z_
Это не совсем то же самое, что даже для одного аргумента требуется скобка. Но он допускает переменное число аргументов в скобках.
Также есть возможность: используйте BOOST_PP_IF, BOOST_PP_EQUAL и BOOST_PP_TUPLE_ELEM, чтобы сделать что-то вроде:
MACRO(1, a)
MACRO(2, (a,b) )
MACRO(3, (a,b,c) )
или так.