Clang: результат выражения не используется с троичным оператором - PullRequest
3 голосов
/ 16 февраля 2012

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

DBG(5) << "Foobar" << std::endl;

5 означает уровень сообщения, если уровень отладки меньше 5, он выиграет 'распечатать сообщение.В настоящее время он реализован следующим образом:

#define DBG(level) !::Logger::IsToDebug((level)) ? : ::Logger::Debug

В основном IsToDebug проверяет, должно ли сообщение быть напечатано, и возвращает true, когда это необходимо.Logger::Debug является std :: ostream.Это также работает с gcc и clang, однако clang генерирует результат выражения неиспользованные предупреждения.Согласно этому электронному письму это тоже не любит меняться.

Префикс с (void) не работает, он будет сотворен только до ?, в результате чегоошибка компиляции (очевидно, что void не может быть преобразован в bool).Другая проблема с этим синтаксисом в том, что он использует расширение gcc .

Выполнение таких действий, как #define DBG(x) if (::Logger::IsToDebug((x))) ::Logger::Debug, решает проблему, но это верный способ сломать вашу программу (if (foo) DBG(1) << "foo"; else ...) (иЯ не могу поместить все это в do { ... } while(0) из-за того, как макрос вызывается.)

Единственное более или менее жизнеспособное решение, которое я придумал, - это это (предполагая, что IsToDebug возвращает либо 0, либо1):

#define DBG(level) for(int dbgtmpvar = ::Logger::IsToDebug((level)); \
                       dbgtmpvar > 0; --dbgtmpvar) ::Logger::Debug

Это похоже на избыточное убийство (не считая затрат времени выполнения)

1 Ответ

4 голосов
/ 16 февраля 2012

Я думаю, что вы должны использовать троичный оператор, как это определено в Стандарте, а не расширение компилятора.Чтобы использовать стандартный троичный оператор, вы должны также предоставить второе выражение.Для этого вы можете определить класс потока, производный от std::ostream, который нигде ничего не печатает.Объект такого класса может использоваться как второе выражение.

class oemptystream : std::ostream
{
     //..
};

extern oemptystream nout; //declaration here, as definition should go to .cpp

затем

#define DBG(level) ::Logger::IsToDebug((level))? nout : ::Logger::Debug

Теперь, если вы используете этот макрос, то во время выполнения выражение будет сокращено до одного из следующих:

nout << "message";

Или это,

::Logger::Debug << "message";

В любом случае, это примерно так:

std::cout << "message";

Так что я надеюсь, что это не должно давать предупреждение компилятору.

...