C ++嵌套预处理器方向

时间:2011-09-26 15:11:02

标签: c++ compiler-construction

我正在使用预处理程序指令来消除一些模板化的运算符定义。 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(%);

这样可行。我现在要做的是有两种操作模式,“调试”和“不调试”,我之前通过#define DEBUG命令设置。我想做这样的事情:

#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; \
} \

但编译器似乎不喜欢这样。我可以使用#ifdef DEBUG为每个案例重新定义整个BINARY_VECTOR_RETURN_OPERATOR,但这不是很优雅。有没有办法按照我的第二个例子的精神实现代码?

4 个答案:

答案 0 :(得分:2)

呃,尽量不要将预处理器用于实际代码。这几乎总是一个非常糟糕的主意。

我曾经将宏重组为模板功能。我对decltypes有一些乐趣,以至于我提取了一个traits类只是为了降低函数定义的复杂性!

我并没有真正看到完全摆脱宏的方法,只是为了在实际操作符重载的声明中保持理智。现在,它只是模板函数operator_impl()的简单传递,并且您应该能够使用#ifdefs作为调试代码。

template <typename T, typename U, typename Op>
struct op_result
{
    typedef vector<decltype( (*((Op*)nullptr)) (*(T*)nullptr, *(U*)nullptr) ) > type;
};

template <typename T, typename U, typename Op>
inline typename op_result<T, U, Op>::type
operator_impl(const vector<T>& A, const vector<U>& B, Op op)
{
    op_result<T, U, Op>::type 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(op(*a, *b));
        ++a; ++b;
    }
    return C;
}

#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
template <class T, class U> \
inline vector<decltype( *(const T*)nullptr optype *(const U*)nullptr)> \
operator optype (const vector<T>& A, const vector<U>& B) \
{ \
    return operator_impl(A, B, [](const T& t, const U& u) {return t optype u;}); \
}

答案 1 :(得分:2)

#if内不能有#define,但您可以在#define控制的代码中使用#if

例如:

#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

如果第一部分和最后部分足够大,您可能想为它们定义宏。

我不是说这是一个好主意,但它确实做了你想做的事。

编辑:感谢@ okorz001在评论中建议更清晰的选择:

#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

显然,真正的代码会使用更好的名称。

答案 2 :(得分:1)

assertBOOST_ASSERT能胜任这项工作吗? (不得不承认我之前从未在宏中放过一个断言 - 所以在幕后这可能只会重现你的问题)

所以,而不是

 #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

写一下

BOOST_ASSERT(A.size() == B.size());  //include  <boost/assert.hpp>

assert(A.size() == B.size());   //include <assert.h>

(以下是boost assertassert.h

的一些固定链接

答案 3 :(得分:0)

可能有一种方法可以按照第二个例子的精神实现代码。 你可以使用if()代替#ifdef这样的

// May not be useful but still...
#ifdef DEBUG 
#define DEBUG 1
#else
#define DEBUG 0
#endif


#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
template <typename T, typename U> \
 // Code within #ifdef.........    \
  if(DEBUG) {               \
      uint n = A.size();    \
      // .............      \
  }// end if \
 // Code after #ifdef.................. \
vector<decltype(T()*U())> C;\
return C; \
} \

请测试一下是否有效。