2008-04-05 05:57:54 +02:00
/*
2009-05-09 03:08:38 +02:00
P . hpp - customised shared_ptr with ordering and type relationships
2010-12-17 23:28:49 +01:00
2008-04-05 05:57:54 +02:00
Copyright ( C ) Lumiera . org
2008 , Hermann Vosseler < Ichthyostega @ web . de >
2010-12-17 23:28:49 +01:00
2008-04-05 05:57:54 +02:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
published by the Free Software Foundation ; either version 2 of
the License , or ( at your option ) any later version .
2008-04-05 05:57:54 +02:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2010-12-17 23:28:49 +01:00
2008-04-05 05:57:54 +02:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
2010-12-17 23:28:49 +01:00
2008-04-05 05:57:54 +02:00
*/
/** @file p.hpp
2009-05-09 03:08:38 +02:00
* * Customised refcounting smart pointer .
2008-04-05 05:57:54 +02:00
* * Template derived from std : : tr1 : : shared_ptr adding total ordering and
* * type relationships implemented by forwarding to the pointees . In all other
* * respects , it should behave exactly as shared_ptr and is able to cooperate
* * and share ownership with other shared_ptr instantiations .
* *
* * By default different instantiations of shared_ptr are completely unrelated types ,
2009-05-09 03:08:38 +02:00
* * even if using inheritance related type parameters for instantiation : a shared_ptr < Media >
2008-04-05 05:57:54 +02:00
* * isn ' t some kind - of shared_ptr < Asset > - - we need to do an explicit static_ptr_cast . Another
* * common problem is the definition of equality and ordering relations for shared_ptr :
* * equality is based on the equality of the managed pointers , while ordering is built upon
* * the ref count . While generally this may be a good compromise , in our case it hinders treating
2009-05-09 03:08:38 +02:00
* * the smart ptrs within the application almost as if they were the objects themselves and proved
2008-04-05 05:57:54 +02:00
* * an obstacle for writing generic helper functions .
* *
* * the P template resolves these problems by implementing the ordering operators in terms of
* * the corresponding operators on the pointee and by allowing to specify a base class smart - ptr
* * as template parameter .
* *
* * @ see asset . hpp
2010-04-02 21:51:39 +02:00
* * @ see custom - shared - ptr - test . cpp
2008-04-05 05:57:54 +02:00
* * @ see orderingofassetstest . cpp
*/
2011-12-02 16:10:03 +01:00
# ifndef LIB_P_H
# define LIB_P_H
2008-04-05 05:57:54 +02:00
2010-04-02 21:30:22 +02:00
# include "lib/error.hpp"
2008-04-05 05:57:54 +02:00
# include <tr1/memory>
2011-12-02 16:10:03 +01:00
namespace lib {
2008-11-26 05:19:59 +01:00
2008-04-05 05:57:54 +02:00
using std : : tr1 : : shared_ptr ;
using std : : tr1 : : weak_ptr ;
/**
2008-12-07 05:36:02 +01:00
* Customised refcounting smart pointer template , built upon
2008-04-05 05:57:54 +02:00
* std : : tr1 : : shared_ptr , but forwarding type relationships and
* ordering operators to the pointee objects .
* @ param TAR the visible pointee type
2008-09-12 03:42:32 +02:00
* @ param BASE the shared - ptr type used as implementation
2008-04-05 05:57:54 +02:00
* @ note if the BASE smart - ptr type used as implementation
* implies another pointer type than the one used on
* the interface ( = type TAR ) , then every access to the
* pointee causes an dynamic cast . Thus the pointee types
* need to support RTTI .
*/
template < class TAR , class BASE = shared_ptr < TAR > >
class P
: public BASE
{
public :
P ( ) : BASE ( ) { }
template < class Y > explicit P ( Y * p ) : BASE ( p ) { }
template < class Y , class D > P ( Y * p , D d ) : BASE ( p , d ) { }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
P ( P const & r ) : BASE ( r ) { }
template < class Y > P ( shared_ptr < Y > const & r ) : BASE ( r ) { }
template < class Y > explicit P ( weak_ptr < Y > const & wr ) : BASE ( wr ) { }
2011-05-24 03:46:32 +02:00
template < class Y > explicit P ( std : : auto_ptr < Y > & ar ) : BASE ( ar ) { }
2008-04-05 05:57:54 +02:00
2011-05-24 03:46:32 +02:00
P & operator = ( P const & r ) { BASE : : operator = ( r ) ; return * this ; }
2008-04-05 05:57:54 +02:00
template < class Y > P & operator = ( shared_ptr < Y > const & sr ) { BASE : : operator = ( sr ) ; return * this ; }
template < class Y > P & operator = ( std : : auto_ptr < Y > & ar ) { BASE : : operator = ( ar ) ; return * this ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
TAR * get ( ) const { return dynamic_cast < TAR * > ( BASE : : get ( ) ) ; }
TAR & operator * ( ) const { return * get ( ) ; }
TAR * operator - > ( ) const { return get ( ) ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
void swap ( P & b ) { BASE : : swap ( b ) ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
private : /* === friend operators injected into enclosing namespace for ADL === */
template < typename _O_ >
friend inline bool
operator = = ( P const & p , P < _O_ > const & q ) { return ( p & & q ) ? ( * p = = * q ) : ( ! p & & ! q ) ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
template < typename _O_ >
friend inline bool
operator ! = ( P const & p , P < _O_ > const & q ) { return ( p & & q ) ? ( * p ! = * q ) : ! ( ! p & & ! q ) ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
template < typename _O_ >
friend inline bool
2010-04-02 21:30:22 +02:00
operator < ( P const & p , P < _O_ > const & q ) { REQUIRE ( p & & q ) ; return * p < * q ; } ///< @note deliberately not allowing comparison on NIL ////TICKET #307 : problem with equality test in associative containers, where equal(a,b) := !(a < b) && !(b < a)
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
template < typename _O_ >
friend inline bool
2010-04-02 21:30:22 +02:00
operator > ( P const & p , P < _O_ > const & q ) { REQUIRE ( p & & q ) ; return * q < * p ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
template < typename _O_ >
friend inline bool
2010-04-02 21:30:22 +02:00
operator < = ( P const & p , P < _O_ > const & q ) { REQUIRE ( p & & q ) ; return * p < = * q ; }
2011-05-24 03:46:32 +02:00
2008-04-05 05:57:54 +02:00
template < typename _O_ >
friend inline bool
2010-04-02 21:30:22 +02:00
operator > = ( P const & p , P < _O_ > const & q ) { REQUIRE ( p & & q ) ; return * p > = * q ; }
2008-04-05 05:57:54 +02:00
} ;
2011-05-24 03:46:32 +02:00
2011-12-02 16:10:03 +01:00
} // namespace lib
2008-04-05 05:57:54 +02:00
# endif