Перегрузка макроса препроцессора C / C ++ на структуру его аргумента - PullRequest
6 голосов
/ 02 марта 2011

Я хотел бы написать макрос препроцессора, который делает одну вещь, если его аргумент является кортежем токенов в скобках, например:

MY_MACRO((x, y))

и что-то еще, если это просто один токен, например так:

MY_MACRO(x)

Возможно ли это?

Как насчет различения количества разделенных пробелами токенов, то есть между MY_MACRO(x) и MY_MACRO(x y)?

Обратите внимание, что яя не пытаюсь перегрузить в зависимости от количества аргументов - во всех случаях это унарный макрос.

EDIT : я готов использовать переменные макросы, если они помогают

Ответы [ 2 ]

7 голосов
/ 02 марта 2011

Что касается вашего первого вопроса, следующие макросы могут соответствовать вашим целям:

#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 голосов
/ 02 марта 2011

Использование 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) )

или около того.

...