Most of my classes have debug variables, and this makes them often look like this:
class A
{
// stuff
#ifndef NDEBUG
int check = 0;
#endif
};
and methods might look like this:
for (/* big loop */) {
// code
#ifndef NDEBUG
check += x;
#endif
}
assert(check == 100);
Few things are uglier than all those #ifndef NDEBUG's. Unfortunately no compiler I know can optimize the check variable away without these #ifndefs (I don't know if that's even allowed).
So I've tried to come up with a solution that would make my life easier. Here's how it looks now:
#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
So in debug mode, DEBUG_VAR(T) just makes a T. Otherwise it makes a "null class" with only no-ops. And my code would look like this:
class A {
// stuff
DEBUG_VAR(int) check;
};
Then I could just use check as if it were a normal variable! Awesome! However, there are still 2 problems that I cannot get solved:
1. It only works with int, float, etc.
The "null class" doesn't have push_back() etc. No biggie. Most debug variables are ints anyway.
2. The "null class" is 1 char wide!!
Every class in C++ is at least 1 char wide. So even in release mode, a class that uses N debug vars will be at least N chars too big. This is in my eyes just unacceptable. It's against the zero-overhead principle which I aim for as much as I can.
So, how do I fix this second problem? Is it even possible to get rid of the #ifndef NDEBUG's without hurting performance in non-debug mode? I accept any good solution, even if it's your darkest C++ wizardry or C++0x.
debug_
or shortdbg_
) or you wont be able to tell which variable is a debug variable and which is not when you are looking at the source file, now that you dont have#ifndef NDEBUG
lines anymore. – Premolar