1

Normally, for classes I don't intend to include in production code I have conditional operators such as the usual:

#ifdef DEBUG_VERSION

This could also be around certain chunks of code that performs additional steps in development mode.

I've just thought (after many years or using the above): What happens if a typo is introduced in the above? It could have great consequences. Pieces of code included (or not included) when the opposite was intended.

So I'm now wondering about alternatives, and thought about creating 2 macro's:

INCLUDE_IN_DEBUG_BUILD
END_INCLUDE_IN_DEBUG_BUILD

If a typo is ever created in these, an error message is created at compile time, forcing the user to correct it. The first would evaluate to "if (1){" in the debug build and "if (0){" in the production build, so any compiler worth using should optimise those lines out, and even if they don't, at least the code inside will never be called.

Now I'm wondering: Is there something I'm missing here? Why does no-one else use something like this?

4

1 回答 1

1

Update: I replaced the header-based approach with a build-system based approach.

You want to be able to disable not just part of the code inside a function, but maybe also in other areas like inside a class or namespace:

struct my_struct {
#ifdef DEBUG_VERSION
    std::string trace_prefix;
#endif
};

So the real question seems to be: How to prevent typos in your #ifdefs? Here's something which does not limit you and which should work well.

Modify your build system to either define DEBUG_VERSION or RELEASE_VERSION. It should be easy to ensure this. Define those to nothing, e.g. -DDEBUG_VERSION or -DRELEASE_VERSION for GCC/Clang.

With this, you can protect your code like this:

#ifdef DEBUG_VERSION
DEBUG_VERSION
// ...
#endif

or

#ifndef DEBUG_VERSION
DEBUG_VERSION
// ...
#else
RELEASE_VERSION
// ...
#endif

And voila, in the second example above, I already added a small typo: #ifndef instead of #ifdef - but the compiler would complain now as DEBUG_VERSION and RELEASE_VERSION are not defined (as in "defined away" by the header) in the corresponding branches.

To make it as safe as possible, you should always have both branches with the two defines, so the first example I gave should be improved to:

#ifdef DEBUG_VERSION
DEBUG_VERSION
// ...
#else
RELEASE_VERSION
#endif

even if the release branch contains no other code/statements. That way you can catch most errors and I think it is quite descriptive. Since the DEBUG_VERSION is replaced with nothing only in the debug branch, all typos will lead to a compile-time error. The same for RELEASE_VERSION.

于 2013-10-21T16:40:01.533 回答