|
Boost : |
From: Daniel Frey (daniel.frey_at_[hidden])
Date: 2002-03-22 05:17:06
Mark Rodgers wrote:
>
> From: "Aleksey Gurtovoy" <agurtovoy_at_[hidden]>
> > Here's a version of 'operators<>' template that allows "lazy"
> instantiation
> > of complementing operators:
>
> What about operations on different types - Duration + Date = Date, etc?
I tried to merge Alexsey's code with some older code of mine. A first
version shows that you can combine them, but there are some problems
with the granularity (I mean, to specify which of the 'friends' should
be used. The code I have is this:
// Play around with operators and their most generic definitions...
namespace boost
{
template< typename Self > class operators
{
private:
Self& self() { return static_cast< Self& >( *this ); }
const Self& self() const { return static_cast< const Self& >(
*this ); }
protected:
inline bool operator!=( const Self& rhs ) const
{
return !( self() == rhs ); // x != y => !( x == y )
}
template< typename T >
inline bool operator!=( const T& rhs ) const
{
return !( self() == rhs ); // x != y => !( x == y )
}
template< typename T >
friend inline bool operator!=( const T& lhs, const Self& rhs )
{
return !( lhs == rhs ); // x != y => !( x == y )
}
//-------------------------------------------------------
inline bool operator>( const Self& rhs ) const
{
return rhs < self(); // x > y => y < x
}
template< typename T >
inline bool operator>( const T& rhs ) const
{
return rhs < self(); // x > y => y < x
}
template< typename T >
friend inline bool operator>( const T& lhs, const Self& rhs )
{
return rhs < lhs; // x > y => y < x
}
//-------------------------------------------------------
inline bool operator<=( const Self& rhs ) const
{
return !( self() > rhs ); // x <= y => !( x > y )
}
template< typename T >
inline bool operator<=( const T& rhs ) const
{
return !( self() > rhs ); // x <= y => !( x > y )
}
template< typename T >
friend inline bool operator<=( const T& lhs, const Self& rhs )
{
return !( lhs > rhs ); // x <= y => !( x > y )
}
//-------------------------------------------------------
inline bool operator>=( const Self& rhs ) const
{
return !( self() < rhs ); // x >= y => !( x < y )
}
// gcc 2.95.2 seems to have a strange bug which forces me
// to make this single operator public. Shouldn't be neccessary
// for other compilers :)
public:
template< typename T >
inline bool operator>=( const T& rhs ) const
{
return !( self() < rhs ); // x >= y => !( x < y )
}
protected:
template< typename T >
friend inline bool operator>=( const T& lhs, const Self& rhs )
{
return !( lhs < rhs ); // x >= y => !( x < y )
}
//-------------------------------------------------------
template< typename T > inline Self& operator-=( const T& rhs )
{
return self() += -rhs; // x - y => x + -y
}
//-------------------------------------------------------
friend inline Self operator+( const Self& lhs, const Self& rhs )
{
return Self( lhs ) += rhs;
}
template< typename T >
friend inline Self operator+( const Self& lhs, const T& rhs )
{
return Self( lhs ) += rhs;
}
template< typename T >
friend inline Self operator+( const T& lhs, const Self& rhs )
{
// Two alternatives are available
return Self( rhs ) += lhs; // x + y => y + x
// return Self( lhs ) += rhs;
// uses conversion-ctor: Self( const T& ), potentially
dangerous
}
//-------------------------------------------------------
friend inline Self operator-( const Self& lhs, const Self& rhs )
{
return Self( lhs ) -= rhs;
}
template< typename T >
friend inline Self operator-( const Self& lhs, const T& rhs )
{
return Self( lhs ) -= rhs;
}
template< typename T >
friend inline Self operator-( const T& lhs, const Self& rhs )
{
// Two alternatives are available
return ( -Self( rhs ) ) += lhs; // x - y => -y + x
// return Self( lhs ) -= rhs;
// uses conversion-ctor: Self( const T& ), potentially
dangerous
}
//-------------------------------------------------------
friend inline Self operator*( const Self& lhs, const Self& rhs )
{
return Self( lhs ) *= rhs;
}
template< typename T > friend inline Self operator*( const Self&
lhs, const T& rhs )
{
return Self( lhs ) *= rhs;
}
template< typename T > friend inline Self operator*( const T& lhs,
const Self& rhs )
{
// Two alternatives are available
return Self( rhs ) *= lhs; // x * y => y * x
// return Self( lhs ) *= rhs; // uses conversion-ctor: Self(
const T& ), potentially dangerous
}
//-------------------------------------------------------
friend inline Self operator/( const Self& lhs, const Self& rhs )
{
return Self( lhs ) /= rhs;
}
template< typename T >
friend inline Self operator/( const Self& lhs, const T& rhs )
{
return Self( lhs ) /= rhs;
}
template< typename T >
friend inline Self operator/( const T& lhs, const Self& rhs )
{
return Self( lhs ) /= rhs;
// uses conversion-ctor: Self( const T& ), potentially
dangerous
}
};
}
namespace X
{
class A : public boost::operators< A >
{
private:
typedef boost::operators< A > ops;
int i_;
public:
explicit A( const int i ) : i_( i ) {}
A( const A& rhs ) : i_( rhs.i_ ) {}
~A() {}
operator int() const
{
return i_;
}
//-------------------------------------------------------
// Special (logical)
// The basics
bool operator==( const A& rhs ) const { return i_ == rhs.i_; }
bool operator<( const A& rhs ) const { return i_ < rhs.i_; }
// Make 'A' work nicely with 'int'
bool operator==( const int rhs ) const { return i_ == rhs; }
bool operator<( const int rhs ) const { return i_ < rhs; }
// Can this be done in a more generic way?
// Self( lhs ) < rhs could be inefficient...
friend bool operator<( const int lhs, const A& rhs )
{
return lhs < rhs.i_;
}
//-------------------------------------------------------
// Special (arithmetic)
// The basics
inline A operator-() const { return A( -i_ ); }
inline A& operator+=( const A& rhs ) { i_ += rhs.i_; return
*this; }
inline A& operator*=( const A& rhs ) { i_ *= rhs.i_; return
*this; }
inline A& operator/=( const A& rhs ) { i_ /= rhs.i_; return
*this; }
// Make 'A' work nicely with 'int'
inline A& operator+=( const int rhs ) { i_ += rhs; return
*this; }
inline A& operator*=( const int rhs ) { i_ *= rhs; return
*this; }
inline A& operator/=( const int rhs ) { i_ /= rhs; return
*this; }
//-------------------------------------------------------
// Generic (logical)
// Same problem as for ++/--
template< typename T >
friend inline bool operator==( const T& lhs, const A& rhs )
{
// Two alternatives are available
return rhs == lhs; // x == y => y == x
// return A( lhs ) == rhs;
// uses conversion-ctor: A( const T& ), potentially
dangerous
}
//-------------------------------------------------------
using ops::operator!=;
using ops::operator>;
using ops::operator<=;
using ops::operator>=;
//-------------------------------------------------------
// Generic (arithmetic)
using ops::operator-=;
// using ops::operator+;
// using ops::operator-;
// using ops::operator*;
// using ops::operator/;
};
}
//----------------------------------------------------------
#include <iostream>
using namespace std;
int main()
{
int i = 1;
X::A a( 1 );
( i += 2 ) += 3;
( a += 2 ) += 3;
cout << i << " " << a << endl
<< ( i + 2 ) << " " << ( a + 2 ) << endl
<< ( 3 + i ) << " " << ( 3 + a ) << endl
<< ( i + i ) << " " << ( a + a ) << endl;
cout << i << " " << a << endl
<< ( i - 2 ) << " " << ( a - 2 ) << endl
<< ( 3 - i ) << " " << ( 3 - a ) << endl
<< ( i - i ) << " " << ( a - a ) << endl;
cout << i << " " << a << endl
<< ( i * 2 ) << " " << ( a * 2 ) << endl
<< ( 3 * i ) << " " << ( 3 * a ) << endl
<< ( i * i ) << " " << ( a * a ) << endl;
cout << i << " " << a << endl
<< ( i / 2 ) << " " << ( a / 2 ) << endl
<< ( 3 / i ) << " " << ( 3 / a ) << endl
<< ( i / i ) << " " << ( a / a ) << endl;
cout << ( i == 2 ) << " " << ( a == 2 ) << endl
<< ( 2 == i ) << " " << ( 2 == a ) << endl
<< ( i == i ) << " " << ( a == a ) << endl;
cout << ( i >= 2 ) << " " << ( a >= 2 ) << endl
<< ( 2 >= i ) << " " << ( 2 >= a ) << endl
<< ( i >= i ) << " " << ( a >= a ) << endl;
return 0;
}
Regards, Daniel
-- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: daniel.frey_at_[hidden], web: http://www.aixigo.de
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk