Reputation: 141
I am using C++ preprocessor macros to selectively ignore some code blocks for testing purposes, e.g.
#ifdef __SAFE
#define note
#define ensure(X) if(X) {} else
#else
#define note while(false)
#define ensure(X) while(false)
#endif
Intuitively, note
executes some code (usually setting some guard variable) and ensure
executes the next code block if the condition is violated. With these macros, I can write:
note { var = true }
ensure(var == true) { throw new std::exception; }
and the code will compile whether __SAFE
is defined or not (and the compiler will most likely get rid of the dummied out code). This is nice because it behaves essentially as an extension of the C++ language.
I would also like to similarly skip some data member declarations in classes when __SAFE
is undefined. The tricks above do not work anymore, since flow control is disallowed inside a class declaration. I would like to declare some macro guard
for which the class:
class A {
guard int x;
}
contains member int x
only when __SAFE
is defined.
Possible solutions:
guard
by //
, thus obtaining the desired result; but they only work in some compilers (in particular, not in g++
). Also, it seems that comment removal takes place before preprocessing, so it probably won't work anyway.#ifdef ... #endif
block. It works, but it is somewhat verbose.guard(X)
as X
if __SAFE
is defined, and as a blank space otherwise. This works too, but it would be great to get rid of the parentheses, and simply grab the argument as "everything until the next semicolon".I know the C++ preprocesor is not very powerful. I would just like to know if there is an aesthetically pleasant solution; otherwise I will simply use the latter option.
Upvotes: 1
Views: 920
Reputation: 5624
Since C++11, you can use a template alias, something like:
struct A {
guarded<int> x;
};
where guarded
is defined as:
#ifdef YOUR_SAFE_MACRO
template<typename T>
using guarded_impl = T;
#define guarded guarded_impl
#else
template<typename T>
struct guarded_impl {};
#define guarded static guarded_impl
#endif
this has also the bonus of giving a linker error if the variable is ODR-used when YOUR_SAFE_MACRO
is off (if on, the dummy static variable is still there, but should be optimized out at link time if unused).
You can do this in < C++11 as well, but it will be slightly more verbose.
That said, I guess note, ensure and guard are too common names to be used as macros and still hope no name clashing will occur, so I'd strongly advise against such a thing ( you've been warned :) )
Moreover, people reading your code will get confused by having a static
hidden in a macro that looks like a template ... a good'ol #ifdef
would be a better solution in my opinion.
Upvotes: 3