I have been tidying up some old C++ code.
I've reduced pages of operator overload functions using a couple of macros:
.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
It still doesn't feel quite right.
It spreads the class over three separate locations: the class declaration itself, declarations for the operators later in the same header, and then in a separate .cxx file the actual definitions.
Is there a cleaner way to implement these operators in C++11?