Препроцессор C, макрос "Перегрузка"
Я пытаюсь сделать какую-то макрос "Перегрузка", чтобы MACRO(что-то) расширялось не так, как MACRO(что-то еще).
Используя фрагмент, который я получил отсюда (я не уверен, что он на 100% переносимый) и некоторые функции из библиотеки Boost PP, я смог заставить его работать:D
//THESE TWO COUNT THE NUMBER OF ARGUMENTS
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
//THIS ONE RETURNS THE PARAMETER AT POSITION _i FROM A LIST OF __VA_ARGS__
#define VA_ARG(_i, ...) BOOST_PP_ARRAY_ELEM(_i, (VA_NARGS(__VA_ARGS__), (__VA_ARGS__)))
//AND THIS ONE IS THE 'OVERLOADED' MACRO ;)
#define TEST(...) BOOST_PP_IF(BOOST_PP_EQUAL(1, VA_NARGS(__VA_ARGS__)), function_A(VA_ARG(0, __VA_ARGS__)), \ //1 parameter
BOOST_PP_IF(BOOST_PP_EQUAL(2, VA_NARGS(__VA_ARGS__)), function_B(VA_ARG(0, __VA_ARGS__) + VA_ARG(1, __VA_ARGS__)), \ //2 parameters
BOOST_PP_IF(BOOST_PP_EQUAL(3, VA_NARGS(__VA_ARGS__)), function_C(VA_ARG(1, __VA_ARGS__) + VA_ARG(2, __VA_ARGS__)), BOOST_PP_EMPTY())) // 3 parameters and so on ...
So TEST(a) = function_A(a)
TEST(a, b) = function_B(a + b)
TEST(a, b, c) = function_C(b + c)
Теперь я все еще скучаю по двум другим вещам, которые я хочу сделать:
(Это мне действительно безразлично, если я никогда не решу это) Я полагаю, что MACRO может быть написано так, что при получении числа "вариантов" и его соответствующего "вывода" генерируется код, подобный приведенному выше. Что-то вроде TEMPLATE(3, function_A(...), function_B(...), function_C(...)) для генерации примера выше.
Что происходит, когда TEST() вызывается без аргументов? Ну, VA_NARGS расширяется до 1. Но первый аргумент ""(ничего). Я пытаюсь найти способ либо обнаружить "нулевые" аргументы в
__VA_ARGS__
или провести различие между "нулевым" и реальным аргументом, чтобы расширить функцию "перегрузки", чтобы реагировать на эту ситуацию. Есть идеи?
1 ответ
Чтобы ответить на ваш вопрос 2 сначала. Да, с помощью переменных макросов также можно обнаружить пустой список аргументов. Объяснение немного длинное, я написал это здесь. Должно быть относительно легко комбинировать этот подход с используемыми вами макросами boost.
На ваш вопрос 1, да, это тоже возможно. Я думаю, что в Boost есть несколько макросов итераторов, которые очень близки к этому, но они выглядят немного пугающими. Если я правильно понимаю, вы должны использовать что-то вроде вложенных списков (a, (b, (c,d)))
не слишком удобно.
(Я написал набор макросов, которые могут достичь этого более напрямую, но, к сожалению, пакет еще не готов к выпуску. Если вы действительно заинтересованы, свяжитесь со мной в частном порядке.)
Редактировать: Пакет P99 публикуется в то же время и содержит много материала по макросу "перегрузка" и типовые макросы.