c++preprocessor

C++ nested preprocessor directions


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?


Solution

  • 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.