【发布时间】:2011-09-26 15:11:02
【问题描述】:
我正在使用预处理器指令来消除一些模板化的运算符定义。例如
#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,但这不是很优雅。有没有办法按照我的第二个例子的精神来实现代码?
【问题讨论】:
-
AFAIK 没有办法做到这一点。我相信你知道这一点,但我会再说一遍。不要这样做,单独定义每个运算符。它不是一个很大的功能,它会大大增加文件的大小;您甚至可以通过在单行上声明这些迭代器来至少删减一行。并且调试模式的错误检查代码可以重构为一个独立的函数。另外,我认为
NDEBUG(用于“非调试”)比DEBUG符号更常见,因此将#ifdef DEBUG更改为#ifndef NDEBUG可能会更好。 -
感谢您的建议。鉴于它实际上只有 4 个运算符,而且它们相当短,我同意使用 #define 来节省空间是一个坏主意。
-
附带说明,我建议您使用
ostringstream而不是sprintf。毕竟这是 C++。 -
好建议!在您的推动下,我想出了一个更好的方法:ostringstream oss (ostringstream::out); oss