Необязательные параметры с макросами C ++ - PullRequest
94 голосов
/ 15 июня 2010

Есть ли способ получить необязательные параметры с помощью макросов C ++?Какая-то перегрузка тоже подойдет.

Ответы [ 14 ]

1 голос
/ 22 февраля 2018

Вы можете использовать BOOST_PP_OVERLOAD из библиотеки boost.

Пример из Официальный документ Boost :

#include <boost/preprocessor/facilities/overload.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>

#define MACRO_1(number) MACRO_2(number,10)
#define MACRO_2(number1,number2) BOOST_PP_ADD(number1,number2)

#if !BOOST_PP_VARIADICS_MSVC

#define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__)

#else

// or for Visual C++

#define MACRO_ADD_NUMBERS(...) \
  BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY())

#endif

MACRO_ADD_NUMBERS(5) // output is 15
MACRO_ADD_NUMBERS(3,6) // output is 9
0 голосов
/ 08 мая 2019

Как большой поклонник ужасных макро-монстров, я хотел бы расширить ответ Джейсона Денга и сделать его действительно пригодным для использования. (К лучшему или к худшему.) Оригинал не очень хорош в использовании, потому что вам нужно модифицировать большой алфавитный суп каждый раз, когда вы хотите создать новый макрос, и еще хуже, если вам нужно другое количество аргументов.

Итак, я сделал версию с этими функциями:

  • 0 аргумент работает
  • от 1 до 16 аргументов без каких-либо изменений в грязной части
  • Легко написать больше функций макроса
  • Протестировано в gcc 10, clang 9, Visual Studio 2017

В настоящее время я только что сделал максимум 16 аргументов, но если вам нужно больше (действительно, сейчас? Вы просто становитесь глупыми ...), вы можете редактировать FUNC_CHOOSER и CHOOSE_FROM_ARG_COUNT, а затем добавить несколько запятых в NO_ARG_EXPANDER.

Пожалуйста, смотрите превосходный ответ Джейсона Денга для более подробной информации о реализации, но я просто оставлю код здесь:

#include <stdio.h>

void realCreate(int x, int y)
{
    printf("(%d, %d)\n", x, y);
}

// This part you put in some library header:
#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, ...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F, ...) FUNC_RECOMPOSER((__VA_ARGS__, \
            F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
            F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))
#define NO_ARG_EXPANDER(FUNC) ,,,,,,,,,,,,,,,,FUNC ## _0
#define MACRO_CHOOSER(FUNC, ...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))
#define MULTI_MACRO(FUNC, ...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)

// When you need to make a macro with default arguments, use this:
#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)
#define CREATE_0() CREATE_1(0)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_2(x, y) \
    do { \
        /* put whatever code you want in the last macro */ \
        realCreate(x, y); \
    } while(0)


int main()
{
    create();
    create(10);
    create(20, 20);
    //create(30, 30, 30);  // Compilation error
    return 0;
}
0 голосов
/ 30 марта 2012

Ни один из приведенных выше примеров (от Дерека Ледбеттера, Дэвида Сорковского и Джо Д) для подсчета аргументов с помощью макросов не работал для меня с использованием Microsoft VCC 10. Аргумент __VA_ARGS__ всегда рассматривается как один аргумент (его обозначение токеном) с ## или нет), поэтому смещение аргумента, на которое опираются эти примеры, не работает.

Итак, короткий ответ, как говорили многие другие выше: нет, вы не можете перегружать макросы или использовать необязательные аргументы для них.

0 голосов
/ 15 июня 2010

В зависимости от того, что вам нужно, вы можете сделать это с помощью var args с макросами.Теперь, необязательные параметры или перегрузка макросов, такого нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...