Удобные стратегии проверки утверждений
-
11-09-2019 - |
Вопрос
Некоторые утверждения являются дорогостоящими, некоторые лучше отключить в рабочем коде.По крайней мере, неясно, должны ли утверждения всегда быть включены.
В моем приложении я хотел бы иметь возможность включать/выключать часть утверждений для каждого файла или класса.
Как это сделать на С++?
Решение
Для деактивации утверждений по всему модулю я бы использовал:
#if defined(assert)
# undef assert
# define assert(x) ((void)0)
#endif
...конечно, это можно упростить, если вы согласны использовать собственный макрос.
#if defined(_NO_ASSERTS)
# define myAssert(x) ((void)0)
#else
# define myAssert(x) assert(x)
#endif
Для деактивации в масштабах всего класса я бы использовал статический константный член класса или перечисление для всего класса в сочетании с пользовательским макросом:
#define myAssert(x) do { if(_CLASS_ASSERT) { assert(x); } } while(0)
class AssertOff
{
enum { _CLASS_ASSERT = 0 }
}
Используя перечисления и статические константы bool, все современные компиляторы должны оптимизировать if(_CLASS_ASSERT) {}
.
Другие советы
Кодирование с использованием утверждений считается хорошим стилем кодирования.
Что касается времени выполнения включение/выключение Вы можете сделать это с помощью логической переменной.Например, в вашем коде вы можете сделать следующее:
Определите переменную, которая будет использоваться для указания того, включены или выключены утверждения в глобальном пространстве имен (например, из вашей функции main() в том же файле).
bool turnOnAssertions;
Определите переменную, как написано ниже, в других файлах, где вы хотите включить/выключить свои утверждения:
extern bool turnOnAssertions;
Итак, манипулируя переменной TurnOnAssertions с помощью пользовательского интерфейса и записывая
if(turnOnAssertions)
assert(…);
вы можете включить/выключить некоторые из ваших утверждений!
Что касается времени компиляции вам следует сделать следующее:
Для вашего компилятора вы должны указать флаг типа –DASSERTIONSON (-Dflag_name [имя флага, вы можете установить все, что захотите])
#ifdef ASSERTIONSON
bool turnOnAssertions = true;
#else
bool turnOnAssertions = false;
#endif
И просто используйте переменную.
Удачи!
Чтобы отключить утверждения для файла C++, вы можете выполнить одно из следующих действий:
- Определите
NDEBUG
константа в верхней части исходного файла. - Добавить
-DNDEBUG
к параметрам компиляции исходного файла.
Большинство IDE и/или инфраструктуры сборки позволяют указывать параметры сборки для каждого файла, так что это простое решение.
Отключить утверждения для каждого класса сложнее, если в одном исходном файле смешано несколько классов или в файлах заголовков имеется много встроенных функций.Вы можете, конечно #define NDEBUG
и #undef NDEBUG
в соответствующих местах.
Поскольку некоторые IDE ожидают возможности установки NDEBUG
для неотладочных сборок вы можете сделать его более расширяемым, выбрав собственное имя макроса, например DISABLE_ASSERT
.Затем включите код, подобный следующему, в общий файл заголовка (который не скомпилирован заранее):
#ifdef DISABLE_ASSERT
#define NDEBUG
#endif