c++嵌套预处理器方向

C++ nested preprocessor directions

本文关键字:方向 处理器 预处理 嵌套 c++      更新时间:2023-10-16

我正在使用预处理器指令来减少一些模板操作符定义的膨胀。例如

#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(%);

这很好。我现在想做的是有两种操作模式,"调试"answers"不调试",这是我之前通过#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,但这不是很优雅。有没有一种方法来实现我的第二个例子的精神代码?

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

例如:

#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

如果first-part和last-part足够大,您可能需要为它们定义宏。

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

EDIT:感谢@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

显然真正的代码会使用更好的名字

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

我尝试将宏重组为模板函数。我在decltypes中得到了一些乐趣,以至于我拿出了一个trait类,只是为了减少函数定义的复杂性!

我真的没有看到完全摆脱宏的方法,只是为了在实际操作符重载的声明中保持理智。然而,现在,它只是一个简单的传递到模板函数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;}); 
}

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 assert和assert.h的解释性链接)

可能有一种方法可以按照第二个示例的精神实现代码。你可以像这样使用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; 
}