Q_ASSERT релиз семантика сборки

Я не могу найти четкое утверждение о семантике Q_ASSERT при сборке релиза. Если нет проверки утверждений, тогда оценивается ли утвержденное выражение вообще?

Рассмотрим следующий код

Q_ASSERT(do_something_report_false_if_failed());

Будет do_something_report_false_if_failed() работать со всеми возможными конфигурациями сборки Qt? Было бы безопаснее (хотя и более многословно и менее читабельно) сделать это вместо этого:

bool is_ok = do_something_report_false_if_failed();
Q_ASSERT(is_ok)

У последнего подхода есть недостаток в том, что ошибки ASSERT менее многословны, но, возможно, он более четко показывает, что оператор выполняется?

9

Решение

Выражение внутри Q_ASSERT будут не оцениваться в не отладочных конфигурациях сборки.

Рассмотрим исходный код ниже из Qt repo.

#if !defined(Q_ASSERT)
#  ifndef QT_NO_DEBUG
#    define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
#  else
#    define Q_ASSERT(cond) qt_noop()
#  endif
#endif

Если QT_NO_DEBUG определяется, то весь Q_ASSERT заявление заменяется qt_noop(), тем самым удаляя любое выражение, которое оно ранее содержало.

Никогда не полагайтесь на какие-либо побочные эффекты, создаваемые выражением внутри Q_ASSERT заявление. Технически все еще возможно гарантировать, что QT_NO_DEBUG не определен в конкретной конфигурации сборки, но это не Good Idea ™.

17

Другие решения

Это, кажется, отличается в Qt5.5 (но не раньше — см. Qt5.4):

#if !defined(Q_ASSERT)
#  if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
#    define Q_ASSERT(cond) do { } while ((false) && (cond))
#  else
#    define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
#  endif
#endif

Сейчас я получаю много «предупреждений C4127: условное выражение является константой» в Visual Studio 2013.

Обновить:
Замечания к выпуску Qt5.5 сказать:

Q_ASSERT теперь расширит условие даже в режиме освобождения, когда
утверждения отключены, хотя и в недоступном пути кода. это
решает предупреждения компилятора о переменных и функциях, которые были
не используется в режиме выпуска, потому что они использовались только в утверждениях.
К сожалению, кодовые базы, которые скрывали эти функции и переменные
через #ifndef нужно будет удалить условные выражения для компиляции с Qt 5.5.

15