c++11 - Tidying up C++ operator overloads -
i have been tidying old c++ code.
i've reduced pages of operator overload functions using couple of macros:
.hpp
// context, long , 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( ) \ ops( a, ) #define bi_( a, b ) \ ops( a, b ) \ ops( b, ) 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
it still doesn't feel quite right.
it spreads class on 3 separate locations: class declaration itself, declarations operators later in same header, , in separate .cxx file actual definitions.
is there cleaner way implement these operators in c++11?
why not use crtp base class provide operators?
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); } };
and use this:
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_; };
running example on ideone.
Comments
Post a Comment