Проблемы с макросом C ++ __VA_ARGS__ - PullRequest
3 голосов
/ 30 апреля 2010

Каковы (если таковые имеются) некоторые потенциальные проблемы с использованием макроса C ++, как это? Будет ли встроенная функция более подходящим решением?

#define EVENT_INFO(_format_, ...) CMyEvent::Generate(__FILE__, __LINE__, CMyEvent::EVT_HIGH, _format_, __VA_ARGS__)

void
CMyEvent::Generate(
    const char* file,                      // filename
    int line,                              // line number
    CMyEvent::LEVEL level,                 // severity level
    const char *format,                    // format of the msg / data
    ...)                                   // variable arguments
{
    // Get a message from the pool
    CMyEvent* p_msg = GetMessageFromPool();
    if(p_msg != NULL)
    {
        va_list arguments; // points to each unnamed argument
        va_start(arguments, format);
        // Fill the object with strings and data.
        p_msg->Fill(file, line, level, 0, format, arguments);
        va_end(arguments);
    }
}

Ответы [ 3 ]

1 голос
/ 30 апреля 2010

Поскольку вы используете C ++, вы можете избежать ловушек при использовании переменных списков аргументов, которые связаны со многими проблемами:

  • Нет проверки количества аргументов
  • Нет проверки типа аргумента

Чтобы сделать его более C ++, сделайте что-то вроде:

#define EVENT_INFO(args) EventLogStream (__FILE__, __LINE__, __PRETTY_FUNCTION__) << args

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

EVENT_INFO ("The answer to " << the_question << " is " << answer); // usually 42

EventLogStream аналогичен объекту cout и, подобно cout, вы можете предоставить вывод, специфичный для класса:

class Vector3D
{
   EventLogStream &operator << (EventLogStream &out) { out << "{" << x << ", " << y << ", " << z << "}"; }
}
1 голос
/ 30 апреля 2010

Если бы вы могли переписать свой обмен сообщениями для использования оператора << (), возможно, используя std :: ostreams с пользовательским буфером потока, вам не понадобились бы переменные аргументы или уродливый (IMHO) макрос, и это выглядело бы очень больше похоже на C ++, чем на C *. 1001 *

0 голосов
/ 30 апреля 2010

variadic macro отлично подходит для ведения журнала. намного лучше, чем использование iostreams. встроенная функция не будет работать, если вы не готовы передать __FILE__, __LINE__ вручную.

Вы можете заключить формат с круглыми скобками для безопасности (не обязательно ИМХО)

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