Макросы перегрузки C

Есть ли лучший способ "перегрузить" такой макрос? Мне нужен макрос, который принимает различное количество параметров.

#define DEBUG_TRACE_1(p1) std::string p[] = {p1}; log _log(__FUNCTION__, p, 1)
#define DEBUG_TRACE_2(p1, p2) std::string p[] = {p1, p2}; log _log(__FUNCTION__, p, 2)
#define DEBUG_TRACE_3(p1, p2, p3) std::string p[] = {p1, p2, p3}; log _log(__FUNCTION__, p, 3)
#define DEBUG_TRACE_4(p1, p2, p3, p4) std::string p[] = {p1, p2, p3, p4}; log _log(__FUNCTION__, p, 4)
#define DEBUG_TRACE_5(p1, p2, p3, p4, p5) std::string p[] = {p1, p2, p3, p4, p5}; log _log(__FUNCTION__, p, 5)

Вызывается как

DEBUG_TRACE_2("more", "params");

Ответ 1

Самый простой способ сделать ваш конкретный пример - с переменным макросом:

#define DEBUG_TRACE(...)                                        \
    do {                                                        \
        std::string p[] = { __VA_ARGS__ };                      \
        log _log(__FUNCTION__, p, (sizeof p) / (sizeof p[0]));  \
    } while (0)

Несколько примечаний:

  • __VA_ARGS__ - это имя для списка разделенных запятыми аргументов, предоставленных макросу
  • Вы можете узнать, сколько их в вашем случае использует sizeof, так как p - статический массив
  • Окружать ваш макрокоманд в do..это часто считается хорошей практикой, потому что он дает переменные (p) область блока, так что пользователи могут по-прежнему иметь переменную с тем же именем вне макроса, а часть while (0) красиво принимает точку с запятой после этого, не нарушая одну строку, если утверждения

Если вам требуется больше гибкости, чем это, вы можете использовать очень аккуратный трюк, чтобы вы могли явно "перегрузить" макрос, чтобы вести себя совершенно по-другому с различным количеством параметров. Однако это делает код более запутанным и его следует использовать только в том случае, если это абсолютно необходимо. Поскольку кажется, что вариационные аргументы будут хорошо подходят для вашего случая использования, я просто предоставил ссылку: http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/

Ответ 2

В макросах можно использовать стандартные переменные args C/С++, по крайней мере в gcc (EDIT: по-видимому, они стандартизованы, а компилятор MS c также имеет их).

См. эту страницу для получения некоторой информации о том, как это работает.

Существует также еще один вопрос на этом сайте, который может быть вам полезен.