我一直在整理一些旧的 C++ 代码。
我使用几个宏减少了运算符重载函数的页面:
.hpp
// for context, Long and Object wrap respective Python primitives
class Long: public Object
{...};
#define OPS( A, B ) \
bool operator == ( A, B ); \
bool operator != ( A, B ); \
bool operator > ( A, B ); \
bool operator < ( A, B ); \
bool operator >= ( A, B ); \
bool operator <= ( A, B );
#define UNI( A ) \
OPS( A, A )
#define BI_( A, B ) \
OPS( A, B ) \
OPS( B, A )
UNI( const Long& )
BI_( const Long& , int )
BI_( const Long& , long )
UNI( const Float& )
BI_( const Float& , double )
#undef BI_
#undef UNI
#undef OPS
#undef OP
.cpp
#define OP( op, l, r, cmpL, cmpR ) \
bool operator op( l, r ) { return cmpL op cmpR; }
#define OPS( ... ) \
OP( != , ##__VA_ARGS__ ) \
OP( == , ##__VA_ARGS__ ) \
OP( > , ##__VA_ARGS__ ) \
OP( >= , ##__VA_ARGS__ ) \
OP( < , ##__VA_ARGS__ ) \
OP( <= , ##__VA_ARGS__ )
#define BI_( a, b, convA, convB ) \
OPS( a, b, convA, convB ) \
OPS( b, a, convB, convA )
OPS( const Long& a, const Long& b , a.as_long() , b.as_long() )
BI_( const Long& a, int b , a.as_long() , b )
BI_( const Long& a, long b , a.as_long() , b )
OPS( const Float& a, const Float& b , a.as_double() , b.as_double() )
BI_( const Float& a, double b , a.as_double() , b )
#undef BI_
#undef OPS
#undef OP
感觉还是不太对。
它将类分布在三个不同的位置:类声明本身、稍后在同一 header 中的运算符声明,然后在单独的 .cxx 文件中实际定义。
在 C++11 中是否有更简洁的方法来实现这些运算符?
最佳答案
为什么不使用 CRTP提供所有运算符的基类?
template<typename C, typename T>
struct ops_base
{
friend bool operator==(const ops_base& l, const ops_base& r)
{
const C& cl = static_cast<const C&>(l);
const C& cr = static_cast<const C&>(r);
return (caster<C, T>::cast(cl) == caster<C, T>::cast(cr));
}
friend bool operator==(const ops_base& l, T r)
{
const C& cl = static_cast<const C&>(l);
return (caster<C, T>::cast(cl) == r);
}
friend bool operator==(T l, const ops_base& r)
{
const C& cr = static_cast<const C&>(r);
return (l == caster<C, T>::cast(cr));
}
friend bool operator!=(const ops_base& l, const ops_base& r)
{ return !(l == r); }
friend bool operator!=(const ops_base& l, T r)
{ return !(l == r); }
friend bool operator!=(T l, const ops_base& r)
{ return !(l == r); }
friend bool operator<(const ops_base& l, const ops_base& r)
{
const C& cl = static_cast<const C&>(l);
const C& cr = static_cast<const C&>(r);
return (caster<C, T>::cast(cl) < caster<C, T>::cast(cr));
}
friend bool operator<(const ops_base& l, T r)
{
const C& cl = static_cast<const C&>(l);
return (caster<C, T>::cast(cl) < r);
}
friend bool operator<(T l, const ops_base& r)
{
const C& cr = static_cast<const C&>(r);
return (l < caster<C, T>::cast(cr));
}
friend bool operator>(const ops_base& l, const ops_base& r)
{
const C& cl = static_cast<const C&>(l);
const C& cr = static_cast<const C&>(r);
return (caster<C, T>::cast(cl) > caster<C, T>::cast(cr));
}
friend bool operator>(const ops_base& l, T r)
{
const C& cl = static_cast<const C&>(l);
return (caster<C, T>::cast(cl) > r);
}
friend bool operator>(T l, const ops_base& r)
{
const C& cr = static_cast<const C&>(r);
return (l > caster<C, T>::cast(cr));
}
friend bool operator<=(const ops_base& l, const ops_base& r)
{ return !(l > r); }
friend bool operator<=(const ops_base& l, T r)
{ return !(l > r); }
friend bool operator<=(T l, const ops_base& r)
{ return !(l > r); }
friend bool operator>=(const ops_base& l, const ops_base& r)
{ return !(l < r); }
friend bool operator>=(const ops_base& l, T r)
{ return !(l < r); }
friend bool operator>=(T l, const ops_base& r)
{ return !(l < r); }
};
然后像这样使用它:
struct Long : ops_base<Long, long>
{
Long(long val) : value_(val) { }
long as_long() const { return value_; }
private:
long value_;
};
struct Float : ops_base<Float, double>
{
Float(double val) : value_(val) { }
double as_double() const { return value_; }
private:
double value_;
};
在 ideone 上运行示例.
关于c++11 - 整理 C++ 运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27168446/