c++嵌套预处理器方向
C++ nested preprocessor directions
我正在使用预处理器指令来减少一些模板操作符定义的膨胀。例如
#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;});
}
assert
或BOOST_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;
}
- #定义c-预处理器常量..我做错了什么
- 预处理器:插入结构名称中的前一个行号
- 如何在c++中实现处理器调度模拟器
- 使用Unreal C++获取VR耳机的世界位置/方向
- C/C++预处理器是否可以检测一些编译器选项
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 在clang++预处理器中确定gcc工具链版本
- 在C++中向零方向近似的最佳方法
- 不同/较旧的处理器运行c++代码的方式是否不同
- 用于交叉编译和CMake的预处理器宏的单元测试
- 垂直方向的 Gtk3+ 旋转按钮 (c/c++)
- 有没有办法在从编译器获取参数时避免预处理器宏?
- OpenVR:向视图方向移动
- 如何比较两个同名的预处理器宏?
- 从预处理器获取 Windows 版本(C++ Win32)
- 如何摆脱为条件编译定义预处理器宏的需要?
- C 预处理器 - 现有定义的预置路径
- VS2015 预处理器定义与点
- 来自逆 vp 矩阵和相机位置的光线方向不正确
- c++嵌套预处理器方向