I'm using preprocessor directives to de-bloat some templated operator definitions. E.g.
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
template <typename T, typename U> \
vector<decltype(T() optype U())> operator optype (const vector<T>& A, const vector<U>& B){ \
vector<decltype(T()*U())> C; \
C.reserve(A.size()); \
typename vector<T>::const_iterator a = A.begin(); \
typename vector<U>::const_iterator b = B.begin(); \
while (a!=A.end()){ \
C.push_back((*a) optype (*b)); \
++a; ++b; \
} \
return C; \
} \
BINARY_VECTOR_RETURN_OPERATOR(*);
BINARY_VECTOR_RETURN_OPERATOR(+);
BINARY_VECTOR_RETURN_OPERATOR(-);
BINARY_VECTOR_RETURN_OPERATOR(%);
So that works fine. What I want to do now is to have two modes of operation, "debug" and "not debug" which I set via a #define DEBUG command earlier. I would like to do something like this:
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
template <typename T, typename U> \
vector<decltype(T() optype U())> operator optype (const vector<T>& A, const vector<U>& B){ \
#ifdef DEBUG
uint n = A.size(); \
if (n != B.size()){ \
char buf[BUFFLEN]; \
sprintf(buf, "Size mismatch in operator+(%s,%s), sizes: (%d, %d), crashing!", \
typeid(A).name(), typeid(B).name(), (int) A.size(), (int) B.size()); \
cout << buf << endl; \
throw("Size Mismatch Error"); \
} \
#endif
vector<decltype(T()*U())> C; \
C.reserve(A.size()); \
typename vector<T>::const_iterator a = A.begin(); \
typename vector<U>::const_iterator b = B.begin(); \
while (a!=A.end()){ \
C.push_back((*a) optype (*b)); \
++a; ++b; \
} \
return C; \
} \
but the compiler doesn't seem to like that. I could redefine the entire BINARY_VECTOR_RETURN_OPERATOR for each case using #ifdef DEBUG around the whole thing, but that's not very elegant. Is there a way to implement the code in the spirit of my second example?
You can't have a #if
inside a #define
, but you can have a #define
inside the code controlled by a #if
.
For example:
#ifdef DEBUG
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
first-part \
debug-code \
last-part
#else
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
first-part \
last-part
#endif
If first-part and last-part are big enough, you might want to define macros for them.
I'm not saying this is a good idea, but it does do what you were trying to do.
EDIT: Thanks to @okorz001 for suggesting a cleaner alternative in a comment:
#ifdef DEBUG
#define DEBUG_CODE (blah, blah)
#else
#define DEBUG_CODE /* nothing */
#endif
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
first-part \
DEBUG_CODE;
last-part
Obviously the real code would use better names.