Макро-вариационный аргумент - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть этот код:

std::string format(const char *fmt, ...);

#define DEBUG(HANDLER, LEVEL, ...) LOG##LEVEL(HANDLER, format(__VA_ARGS__))

Он работает, когда я использую:

DEBUG(handler, DEBUG, "var is %d\n", 15);

, но не работает, когда я использую:

DEBUG(handler, DEBUG, "test");

Как я могу проверить, есть ли только один аргумент или более одного?
Мне нужно использовать только решение C ++ 98 .

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Итак, я посмотрел на ваш вопрос, посмотрел на ваш код и понял, что это, вероятно, случай печально известной проблемы XY .

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

DEBUG(handler, DEBUG, "test");

Но это, конечно, возможно.И чтобы проверить это, я написал следующий фрагмент кода:

std::string format(const char* fmt, ...) {
    char buffer[256];
    std::cout << __FUNCTION__ << std::endl;
    va_list argList;
    va_start(argList, fmt);
    vsprintf(buffer, fmt, argList);
    va_end(argList);
    return std::string(buffer);
}

#define TRC(...) {\
    std::cout << "MACRO!" << std::endl; \
    std::cout << format(__VA_ARGS__);\
}

int main()
{
    std::cout << "Hello World!" << std::endl;
    const char *t = "b";
    TRC("[%s] bla bla [%d]\n", t, 9);
    TRC("test");
    return 0;
}

, который производит вывод,

Hello World!
МАКРО!
формат
[b] бла бла [9]
MACRO!
формат
тест

Как я уже упоминал в комментариях к вашему вопросу, у меня есть C++03 компилятор, но это должно работать и для C ++ 98, я думаю.

Вопрос:

«Как я могу проверить, есть ли только один аргумент или более одного?»

У самого макроса variadic нет проблем, есть ли у вас один аргумент или более.

Но если вы действительно хотите посчитать количество переданных аргументов, я не знаю, как это сделать в C++03 или ранее.

0 голосов
/ 12 февраля 2019

Поскольку __VA__ARGS__ доступен на вашем компиляторе C ++ 98 (несмотря на то, что он C ++ 11 ), есть вероятность, что он также имеет __VA_OPT__ в качестве расширения:

Вы должны использовать __VA_OPT__(something) (что является функцией C ++ 20), чтобы запятая появлялась, только если есть хотя бы один аргумент:

#define DEBUG(HANDLER, LEVEL, ...) LOG##LEVEL(HANDLER __VA_OPT__( format(__VA_ARGS__)))

или что-то подобное, что работает для вашегослучай.

...