LUMIERA.clone/src/common/p.hpp

128 lines
5 KiB
C++

/*
P.hpp - customized shared_ptr with ordering and type relationships
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
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.
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 02139, USA.
*/
/** @file p.hpp
** customized refcounting smart pointer.
** 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,
** even if using inherintance related type parameters for instantiation: a shared_ptr<Media>
** 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
** the smart ptrs within the application almost as if they were the objects themselfs and proved
** 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
** @see customsharedptrtest.cpp
** @see orderingofassetstest.cpp
*/
#ifndef LUMIERA_P_H
#define LUMIERA_P_H
#include <tr1/memory>
namespace lumiera {
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
/**
* customized refcounting smart pointer template, built upon
* std::tr1::shared_ptr, but forwarding type relationships and
* ordering operators to the pointee objects.
* @param TAR the visible pointee type
* @param BASE the shared-ptr type used as implementation
* @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){}
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) {}
template<class Y> explicit P (std::auto_ptr<Y> & ar) : BASE(ar) {}
P& operator= (P const& r) { BASE::operator= (r); return *this; }
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; }
TAR* get() const { return dynamic_cast<TAR*> (BASE::get()); }
TAR& operator*() const { return *get(); }
TAR* operator->() const { return get(); }
void swap(P& b) { BASE::swap (b);}
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); }
template<typename _O_>
friend inline bool
operator!= (P const& p, P<_O_> const& q) { return (p && q)? (*p != *q) : !(!p && !q); }
template<typename _O_>
friend inline bool
operator< (P const& p, P<_O_> const& q) { return (p && q) && (*p < *q); }
template<typename _O_>
friend inline bool
operator> (P const& p, P<_O_> const& q) { return (p && q) && (*q < *p); }
template<typename _O_>
friend inline bool
operator<= (P const& p, P<_O_> const& q) { return (p && q)? (*p <= *q) : (!p && !q); }
template<typename _O_>
friend inline bool
operator>= (P const& p, P<_O_> const& q) { return (p && q)? (*p >= *q) : (!p && !q); }
};
} // namespace lumiera
#endif