Большинство моих классов имеют переменные отладки, и поэтому они часто выглядят так:
class A
{
// stuff
#ifndef NDEBUG
int check = 0;
#endif
};
, а методы могут выглядеть следующим образом:
for (/* big loop */) {
// code
#ifndef NDEBUG
check += x;
#endif
}
assert(check == 100);
Мало что страшнее, чемвсе эти #ifndef NDEBUG.К сожалению, ни один из известных мне компиляторов не может оптимизировать переменную check без этих #ifndefs (я не знаю, разрешено ли это вообще).
Поэтому я попытался найти решениеэто сделало бы мою жизнь проще.Вот как это выглядит сейчас:
#ifndef NDEBUG
#define DEBUG_VAR(T) T
#else
template <typename T>
struct nullclass {
inline void operator+=(const T&) const {}
inline const nullclass<T>& operator+(const T&) const { return *this; }
// more no-op operators...
};
#define DEBUG_VAR(T) nullclass<T>
#endif
Итак, в режиме отладки DEBUG_VAR (T) просто создает T. В противном случае он создает «нулевой класс» только с no-ops.И мой код будет выглядеть так:
class A {
// stuff
DEBUG_VAR(int) check;
};
Тогда я мог бы просто использовать check , как если бы это была обычная переменная!Потрясающие!Тем не менее, есть еще 2 проблемы, которые я не могу решить:
1.Он работает только с int, float и т. Д.
«Нулевой класс» не имеет push_back () и т. Д. Нет, biggie.В любом случае большинство отладочных переменных являются целочисленными.
2.«Нулевой класс» имеет ширину 1 символ !!
Каждый класс в C ++ имеет ширину не менее 1 символа.Таким образом, даже в режиме выпуска класс, использующий N отладочных переменных, будет по крайней мере на N символов слишком большим.Это на мой взгляд просто недопустимо.Это против принципа отсутствия накладных расходов, к которому я стремлюсь столько, сколько могу.
Итак, как мне решить эту вторую проблему? Можно ли вообще избавиться от #ifndefNDEBUG без ущерба для производительности в режиме без отладки?Я принимаю любое хорошее решение, даже если это ваше самое темное волшебство C ++ или C ++ 0x.