summaryrefslogtreecommitdiff
path: root/shared/loki/SmartPtr.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/loki/SmartPtr.h')
-rw-r--r--shared/loki/SmartPtr.h1778
1 files changed, 1778 insertions, 0 deletions
diff --git a/shared/loki/SmartPtr.h b/shared/loki/SmartPtr.h
new file mode 100644
index 00000000..df548553
--- /dev/null
+++ b/shared/loki/SmartPtr.h
@@ -0,0 +1,1778 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SMARTPTR_INC_
+#define LOKI_SMARTPTR_INC_
+
+// $Id: SmartPtr.h 903 2008-11-10 05:55:12Z rich_sposato $
+
+
+/// \defgroup SmartPointerGroup Smart pointers
+/// Policy based implementation of a smart pointer
+/// \defgroup SmartPointerOwnershipGroup Ownership policies
+/// \ingroup SmartPointerGroup
+/// \defgroup SmartPointerStorageGroup Storage policies
+/// \ingroup SmartPointerGroup
+/// \defgroup SmartPointerConversionGroup Conversion policies
+/// \ingroup SmartPointerGroup
+/// \defgroup SmartPointerCheckingGroup Checking policies
+/// \ingroup SmartPointerGroup
+
+#include "LokiExport.h"
+#include "SmallObj.h"
+#include "TypeManip.h"
+#include "static_check.h"
+#include "RefToValue.h"
+#include "ConstPolicy.h"
+
+#include <functional>
+#include <stdexcept>
+#include <cassert>
+#include <string>
+
+#if !defined(_MSC_VER)
+# if defined(__sparc__)
+# include <inttypes.h>
+# else
+# include <stdint.h>
+# endif
+#endif
+
+#if defined(_MSC_VER) || defined(__GNUC__)
+// GCC>=4.1 must use -ffriend-injection due to a bug in GCC
+#define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+#endif
+
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class HeapStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the StoragePolicy used by SmartPtr. Uses explicit call
+/// to T's destructor followed by call to free.
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class T>
+ class HeapStorage
+ {
+ public:
+ typedef T* StoredType; /// the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef T* PointerType; /// type returned by operator->
+ typedef T& ReferenceType; /// type returned by operator*
+
+ HeapStorage() : pointee_(Default())
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ HeapStorage(const HeapStorage&) : pointee_(0)
+ {}
+
+ template <class U>
+ HeapStorage(const HeapStorage<U>&) : pointee_(0)
+ {}
+
+ HeapStorage(const StoredType& p) : pointee_(p) {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(HeapStorage& rhs)
+ { std::swap(pointee_, rhs.pointee_); }
+
+ // Accessors
+ template <class F>
+ friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp);
+
+ template <class F>
+ friend const typename HeapStorage<F>::StoredType& GetImplRef(const HeapStorage<F>& sp);
+
+ template <class F>
+ friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ {
+ if ( 0 != pointee_ )
+ {
+ pointee_->~T();
+ ::free( pointee_ );
+ }
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename HeapStorage<T>::StoredType& GetImplRef(const HeapStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename HeapStorage<T>::StoredType& GetImplRef(HeapStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DefaultSPStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the StoragePolicy used by SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class T>
+ class DefaultSPStorage
+ {
+ public:
+ typedef T* StoredType; // the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef T* PointerType; // type returned by operator->
+ typedef T& ReferenceType; // type returned by operator*
+
+ DefaultSPStorage() : pointee_(Default())
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ DefaultSPStorage(const DefaultSPStorage&) : pointee_(0)
+ {}
+
+ template <class U>
+ DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
+ {}
+
+ DefaultSPStorage(const StoredType& p) : pointee_(p) {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(DefaultSPStorage& rhs)
+ { std::swap(pointee_, rhs.pointee_); }
+
+ // Accessors
+ template <class F>
+ friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp);
+
+ template <class F>
+ friend const typename DefaultSPStorage<F>::StoredType& GetImplRef(const DefaultSPStorage<F>& sp);
+
+ template <class F>
+ friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ //
+ // If your compiler gives you a warning in this area while
+ // compiling the tests, it is on purpose, please ignore it.
+ void Destroy()
+ {
+ delete pointee_;
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename DefaultSPStorage<T>::StoredType& GetImplRef(const DefaultSPStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename DefaultSPStorage<T>::StoredType& GetImplRef(DefaultSPStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class LockedStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the StoragePolicy used by SmartPtr.
+///
+/// Each call to operator-> locks the object for the duration of a call to a
+/// member function of T.
+///
+/// \par How It Works
+/// LockedStorage has a helper class called Locker, which acts as a smart
+/// pointer with limited abilities. LockedStorage::operator-> returns an
+/// unnamed temporary of type Locker<T> that exists for the duration of the
+/// call to a member function of T. The unnamed temporary locks the object
+/// when it is constructed by operator-> and unlocks the object when it is
+/// destructed.
+///
+/// \note This storage policy requires class T to have member functions Lock
+/// and Unlock. If your class does not have Lock or Unlock functions, you may
+/// either make a child class which does, or make a policy class similar to
+/// LockedStorage which calls other functions to lock the object.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class Locker
+ {
+ public:
+ Locker( const T * p ) : pointee_( const_cast< T * >( p ) )
+ {
+ if ( pointee_ != 0 )
+ pointee_->Lock();
+ }
+
+ ~Locker( void )
+ {
+ if ( pointee_ != 0 )
+ pointee_->Unlock();
+ }
+
+ operator T * ()
+ {
+ return pointee_;
+ }
+
+ T * operator->()
+ {
+ return pointee_;
+ }
+
+ private:
+ Locker( void );
+ Locker & operator = ( const Locker & );
+ T * pointee_;
+ };
+
+ template <class T>
+ class LockedStorage
+ {
+ public:
+
+ typedef T* StoredType; /// the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef Locker< T > PointerType; /// type returned by operator->
+ typedef T& ReferenceType; /// type returned by operator*
+
+ LockedStorage() : pointee_( Default() ) {}
+
+ ~LockedStorage( void ) {}
+
+ LockedStorage( const LockedStorage&) : pointee_( 0 ) {}
+
+ LockedStorage( const StoredType & p ) : pointee_( p ) {}
+
+ PointerType operator->()
+ {
+ return Locker< T >( pointee_ );
+ }
+
+ void Swap(LockedStorage& rhs)
+ {
+ std::swap( pointee_, rhs.pointee_ );
+ }
+
+ // Accessors
+ template <class F>
+ friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp);
+
+ template <class F>
+ friend const typename LockedStorage<F>::StoredType& GetImplRef(const LockedStorage<F>& sp);
+
+ template <class F>
+ friend typename LockedStorage<F>::StoredType& GetImplRef(LockedStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ {
+ delete pointee_;
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ /// Dereference operator is not implemented.
+ ReferenceType operator*();
+
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename LockedStorage<T>::StoredType& GetImplRef(const LockedStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class ArrayStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the ArrayStorage used by SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class T>
+ class ArrayStorage
+ {
+ public:
+ typedef T* StoredType; // the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef T* PointerType; // type returned by operator->
+ typedef T& ReferenceType; // type returned by operator*
+
+ ArrayStorage() : pointee_(Default())
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ ArrayStorage(const ArrayStorage&) : pointee_(0)
+ {}
+
+ template <class U>
+ ArrayStorage(const ArrayStorage<U>&) : pointee_(0)
+ {}
+
+ ArrayStorage(const StoredType& p) : pointee_(p) {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(ArrayStorage& rhs)
+ { std::swap(pointee_, rhs.pointee_); }
+
+ // Accessors
+ template <class F>
+ friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp);
+
+ template <class F>
+ friend const typename ArrayStorage<F>::StoredType& GetImplRef(const ArrayStorage<F>& sp);
+
+ template <class F>
+ friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ { delete [] pointee_; }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename ArrayStorage<T>::StoredType& GetImplRef(const ArrayStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename ArrayStorage<T>::StoredType& GetImplRef(ArrayStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class RefCounted
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Provides a classic external reference counting implementation
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class RefCounted
+ {
+ public:
+ RefCounted()
+ : pCount_(static_cast<uintptr_t*>(
+ SmallObject<>::operator new(sizeof(uintptr_t))))
+ {
+ assert(pCount_!=0);
+ *pCount_ = 1;
+ }
+
+ RefCounted(const RefCounted& rhs)
+ : pCount_(rhs.pCount_)
+ {}
+
+ // MWCW lacks template friends, hence the following kludge
+ template <typename P1>
+ RefCounted(const RefCounted<P1>& rhs)
+ : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
+ {}
+
+ P Clone(const P& val)
+ {
+ ++*pCount_;
+ return val;
+ }
+
+ bool Release(const P&)
+ {
+ if (!--*pCount_)
+ {
+ SmallObject<>::operator delete(pCount_, sizeof(uintptr_t));
+ pCount_ = NULL;
+ return true;
+ }
+ return false;
+ }
+
+ void Swap(RefCounted& rhs)
+ { std::swap(pCount_, rhs.pCount_); }
+
+ enum { destructiveCopy = false };
+
+ private:
+ // Data
+ uintptr_t* pCount_;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RefCountedMT
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements external reference counting for multithreaded programs
+/// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
+///
+/// \par Warning
+/// There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release"
+/// http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644
+/// As stated in bug 1408845, the Release function is not thread safe if a
+/// SmartPtr copy-constructor tries to copy the last pointer to an object in
+/// one thread, while the destructor is acting on the last pointer in another
+/// thread. The existence of a race between a copy-constructor and destructor
+/// implies a design flaw at a higher level. That race condition must be
+/// fixed at a higher design level, and no change to this class could fix it.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <template <class, class> class ThreadingModel,
+ class MX = LOKI_DEFAULT_MUTEX >
+ struct RefCountedMTAdj
+ {
+ template <class P>
+ class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX >
+ {
+ typedef ThreadingModel< RefCountedMT<P>, MX > base_type;
+ typedef typename base_type::IntType CountType;
+ typedef volatile CountType *CountPtrType;
+
+ public:
+ RefCountedMT()
+ {
+ pCount_ = static_cast<CountPtrType>(
+ SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new(
+ sizeof(*pCount_)));
+ assert(pCount_);
+ //*pCount_ = 1;
+ ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
+ }
+
+ RefCountedMT(const RefCountedMT& rhs)
+ : pCount_(rhs.pCount_)
+ {}
+
+ //MWCW lacks template friends, hence the following kludge
+ template <typename P1>
+ RefCountedMT(const RefCountedMT<P1>& rhs)
+ : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
+ {}
+
+ P Clone(const P& val)
+ {
+ ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_);
+ return val;
+ }
+
+ bool Release(const P&)
+ {
+ bool isZero = false;
+ ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero );
+ if ( isZero )
+ {
+ SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete(
+ const_cast<CountType *>(pCount_),
+ sizeof(*pCount_));
+ return true;
+ }
+ return false;
+ }
+
+ void Swap(RefCountedMT& rhs)
+ { std::swap(pCount_, rhs.pCount_); }
+
+ enum { destructiveCopy = false };
+
+ private:
+ // Data
+ CountPtrType pCount_;
+ };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class COMRefCounted
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class COMRefCounted
+ {
+ public:
+ COMRefCounted()
+ {}
+
+ template <class U>
+ COMRefCounted(const COMRefCounted<U>&)
+ {}
+
+ static P Clone(const P& val)
+ {
+ if(val!=0)
+ val->AddRef();
+ return val;
+ }
+
+ static bool Release(const P& val)
+ {
+ if(val!=0)
+ val->Release();
+ return false;
+ }
+
+ enum { destructiveCopy = false };
+
+ static void Swap(COMRefCounted&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct DeepCopy
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements deep copy semantics, assumes existence of a Clone() member
+/// function of the pointee type
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct DeepCopy
+ {
+ DeepCopy()
+ {}
+
+ template <class P1>
+ DeepCopy(const DeepCopy<P1>&)
+ {}
+
+ static P Clone(const P& val)
+ { return val->Clone(); }
+
+ static bool Release(const P&)
+ { return true; }
+
+ static void Swap(DeepCopy&)
+ {}
+
+ enum { destructiveCopy = false };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class RefLinked
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements reference linking
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ class LOKI_EXPORT RefLinkedBase
+ {
+ public:
+ RefLinkedBase()
+ { prev_ = next_ = this; }
+
+ RefLinkedBase(const RefLinkedBase& rhs);
+
+ bool Release();
+
+ void Swap(RefLinkedBase& rhs);
+
+ bool Merge( RefLinkedBase & rhs );
+
+ enum { destructiveCopy = false };
+
+ private:
+ static unsigned int CountPrevCycle( const RefLinkedBase * pThis );
+ static unsigned int CountNextCycle( const RefLinkedBase * pThis );
+ bool HasPrevNode( const RefLinkedBase * p ) const;
+ bool HasNextNode( const RefLinkedBase * p ) const;
+
+ mutable const RefLinkedBase* prev_;
+ mutable const RefLinkedBase* next_;
+ };
+ }
+
+ template <class P>
+ class RefLinked : public Private::RefLinkedBase
+ {
+ public:
+ RefLinked()
+ {}
+
+ template <class P1>
+ RefLinked(const RefLinked<P1>& rhs)
+ : Private::RefLinkedBase(rhs)
+ {}
+
+ static P Clone(const P& val)
+ { return val; }
+
+ bool Release(const P&)
+ { return Private::RefLinkedBase::Release(); }
+
+ template < class P1 >
+ bool Merge( RefLinked< P1 > & rhs )
+ {
+ return Private::RefLinkedBase::Merge( rhs );
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DestructiveCopy
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements destructive copy semantics (a la std::auto_ptr)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class DestructiveCopy
+ {
+ public:
+ DestructiveCopy()
+ {}
+
+ template <class P1>
+ DestructiveCopy(const DestructiveCopy<P1>&)
+ {}
+
+ template <class P1>
+ static P Clone(P1& val)
+ {
+ P result(val);
+ val = P1();
+ return result;
+ }
+
+ static bool Release(const P&)
+ { return true; }
+
+ static void Swap(DestructiveCopy&)
+ {}
+
+ enum { destructiveCopy = true };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class NoCopy
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements a policy that doesn't allow copying objects
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class NoCopy
+ {
+ public:
+ NoCopy()
+ {}
+
+ template <class P1>
+ NoCopy(const NoCopy<P1>&)
+ {}
+
+ static P Clone(const P&)
+ {
+ // Make it depended on template parameter
+ static const bool DependedFalse = sizeof(P*) == 0;
+
+ LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
+ }
+
+ static bool Release(const P&)
+ { return true; }
+
+ static void Swap(NoCopy&)
+ {}
+
+ enum { destructiveCopy = false };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct AllowConversion
+///
+/// \ingroup SmartPointerConversionGroup
+/// Implementation of the ConversionPolicy used by SmartPtr
+/// Allows implicit conversion from SmartPtr to the pointee type
+////////////////////////////////////////////////////////////////////////////////
+
+ struct AllowConversion
+ {
+ enum { allow = true };
+
+ void Swap(AllowConversion&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct DisallowConversion
+///
+/// \ingroup SmartPointerConversionGroup
+/// Implementation of the ConversionPolicy used by SmartPtr
+/// Does not allow implicit conversion from SmartPtr to the pointee type
+/// You can initialize a DisallowConversion with an AllowConversion
+////////////////////////////////////////////////////////////////////////////////
+
+ struct DisallowConversion
+ {
+ DisallowConversion()
+ {}
+
+ DisallowConversion(const AllowConversion&)
+ {}
+
+ enum { allow = false };
+
+ void Swap(DisallowConversion&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct NoCheck
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Well, it's clear what it does :o)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct NoCheck
+ {
+ NoCheck()
+ {}
+
+ template <class P1>
+ NoCheck(const NoCheck<P1>&)
+ {}
+
+ static void OnDefault(const P&)
+ {}
+
+ static void OnInit(const P&)
+ {}
+
+ static void OnDereference(const P&)
+ {}
+
+ static void Swap(NoCheck&)
+ {}
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct AssertCheck
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct AssertCheck
+ {
+ AssertCheck()
+ {}
+
+ template <class P1>
+ AssertCheck(const AssertCheck<P1>&)
+ {}
+
+ template <class P1>
+ AssertCheck(const NoCheck<P1>&)
+ {}
+
+ static void OnDefault(const P&)
+ {}
+
+ static void OnInit(const P&)
+ {}
+
+ static void OnDereference(P val)
+ { assert(val); (void)val; }
+
+ static void Swap(AssertCheck&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct AssertCheckStrict
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer against zero upon initialization and before dereference
+/// You can initialize an AssertCheckStrict with an AssertCheck
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct AssertCheckStrict
+ {
+ AssertCheckStrict()
+ {}
+
+ template <class U>
+ AssertCheckStrict(const AssertCheckStrict<U>&)
+ {}
+
+ template <class U>
+ AssertCheckStrict(const AssertCheck<U>&)
+ {}
+
+ template <class P1>
+ AssertCheckStrict(const NoCheck<P1>&)
+ {}
+
+ static void OnDefault(P val)
+ { assert(val); }
+
+ static void OnInit(P val)
+ { assert(val); }
+
+ static void OnDereference(P val)
+ { assert(val); }
+
+ static void Swap(AssertCheckStrict&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct NullPointerException
+///
+/// \ingroup SmartPointerGroup
+/// Used by some implementations of the CheckingPolicy used by SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+ struct NullPointerException : public std::runtime_error
+ {
+ NullPointerException() : std::runtime_error(std::string(""))
+ { }
+ const char* what() const throw()
+ { return "Null Pointer Exception"; }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RejectNullStatic
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer upon initialization and before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct RejectNullStatic
+ {
+ RejectNullStatic()
+ {}
+
+ template <class P1>
+ RejectNullStatic(const RejectNullStatic<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStatic(const NoCheck<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStatic(const AssertCheck<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStatic(const AssertCheckStrict<P1>&)
+ {}
+
+ static void OnDefault(const P&)
+ {
+ // Make it depended on template parameter
+ static const bool DependedFalse = sizeof(P*) == 0;
+
+ LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
+ }
+
+ static void OnInit(const P& val)
+ { if (!val) throw NullPointerException(); }
+
+ static void OnDereference(const P& val)
+ { if (!val) throw NullPointerException(); }
+
+ static void Swap(RejectNullStatic&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RejectNull
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct RejectNull
+ {
+ RejectNull()
+ {}
+
+ template <class P1>
+ RejectNull(const RejectNull<P1>&)
+ {}
+
+ static void OnInit(P)
+ {}
+
+ static void OnDefault(P)
+ {}
+
+ void OnDereference(P val)
+ { if (!val) throw NullPointerException(); }
+
+ void OnDereference(P val) const
+ { if (!val) throw NullPointerException(); }
+
+ void Swap(RejectNull&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RejectNullStrict
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer upon initialization and before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct RejectNullStrict
+ {
+ RejectNullStrict()
+ {}
+
+ template <class P1>
+ RejectNullStrict(const RejectNullStrict<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStrict(const RejectNull<P1>&)
+ {}
+
+ static void OnInit(P val)
+ { if (!val) throw NullPointerException(); }
+
+ void OnDereference(P val)
+ { OnInit(val); }
+
+ void OnDereference(P val) const
+ { OnInit(val); }
+
+ void Swap(RejectNullStrict&)
+ {}
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class template SmartPtr (declaration)
+// The reason for all the fuss above
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OwnershipPolicy = RefCounted,
+ class ConversionPolicy = DisallowConversion,
+ template <class> class CheckingPolicy = AssertCheck,
+ template <class> class StoragePolicy = DefaultSPStorage,
+ template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
+ >
+ class SmartPtr;
+
+////////////////////////////////////////////////////////////////////////////////
+// class template SmartPtrDef (definition)
+// this class added to unify the usage of SmartPtr
+// instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OwnershipPolicy = RefCounted,
+ class ConversionPolicy = DisallowConversion,
+ template <class> class CheckingPolicy = AssertCheck,
+ template <class> class StoragePolicy = DefaultSPStorage,
+ template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
+ >
+ struct SmartPtrDef
+ {
+ typedef SmartPtr
+ <
+ T,
+ OwnershipPolicy,
+ ConversionPolicy,
+ CheckingPolicy,
+ StoragePolicy,
+ ConstnessPolicy
+ >
+ type;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SmartPtr
+///
+/// \ingroup SmartPointerGroup
+///
+/// \param OwnershipPolicy default = RefCounted,
+/// \param ConversionPolicy default = DisallowConversion,
+/// \param CheckingPolicy default = AssertCheck,
+/// \param StoragePolicy default = DefaultSPStorage
+/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
+///
+/// \par IMPORTANT NOTE
+/// Due to threading issues, the OwnershipPolicy has been changed as follows:
+///
+/// - Release() returns a boolean saying if that was the last release
+/// so the pointer can be deleted by the StoragePolicy
+/// - IsUnique() was removed
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OwnershipPolicy,
+ class ConversionPolicy,
+ template <class> class CheckingPolicy,
+ template <class> class StoragePolicy,
+ template <class> class ConstnessPolicy
+ >
+ class SmartPtr
+ : public StoragePolicy<T>
+ , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
+ , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
+ , public ConversionPolicy
+ {
+ typedef StoragePolicy<T> SP;
+ typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
+ typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
+ typedef ConversionPolicy CP;
+
+ public:
+ typedef typename ConstnessPolicy<T>::Type* ConstPointerType;
+ typedef typename ConstnessPolicy<T>::Type& ConstReferenceType;
+
+ typedef typename SP::PointerType PointerType;
+ typedef typename SP::StoredType StoredType;
+ typedef typename SP::ReferenceType ReferenceType;
+
+ typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
+ CopyArg;
+
+ private:
+ struct NeverMatched {};
+
+#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
+ typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
+ typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
+#else
+ typedef const StoredType& ImplicitArg;
+ typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
+#endif
+
+ public:
+
+ SmartPtr()
+ {
+ KP::OnDefault(GetImpl(*this));
+ }
+
+ explicit
+ SmartPtr(ExplicitArg p) : SP(p)
+ {
+ KP::OnInit(GetImpl(*this));
+ }
+
+ SmartPtr(ImplicitArg p) : SP(p)
+ {
+ KP::OnInit(GetImpl(*this));
+ }
+
+ SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ {
+ GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
+ }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ {
+ GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
+ }
+
+ SmartPtr(RefToValue<SmartPtr> rhs)
+ : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ {}
+
+ operator RefToValue<SmartPtr>()
+ { return RefToValue<SmartPtr>(*this); }
+
+ SmartPtr& operator=(CopyArg& rhs)
+ {
+ SmartPtr temp(rhs);
+ temp.Swap(*this);
+ return *this;
+ }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ {
+ SmartPtr temp(rhs);
+ temp.Swap(*this);
+ return *this;
+ }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ {
+ SmartPtr temp(rhs);
+ temp.Swap(*this);
+ return *this;
+ }
+
+ void Swap(SmartPtr& rhs)
+ {
+ OP::Swap(rhs);
+ CP::Swap(rhs);
+ KP::Swap(rhs);
+ SP::Swap(rhs);
+ }
+
+ ~SmartPtr()
+ {
+ if (OP::Release(GetImpl(*static_cast<SP*>(this))))
+ {
+ SP::Destroy();
+ }
+ }
+
+#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+
+ // old non standard in class definition of friends
+ friend inline void Release(SmartPtr& sp, typename SP::StoredType& p)
+ {
+ p = GetImplRef(sp);
+ GetImplRef(sp) = SP::Default();
+ }
+
+ friend inline void Reset(SmartPtr& sp, typename SP::StoredType p)
+ { SmartPtr(p).Swap(sp); }
+
+#else
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
+ typename SP1<T1>::StoredType& p);
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
+ typename SP1<T1>::StoredType p);
+#endif
+
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ if ( GetImpl( *this ) != GetImpl( rhs ) )
+ {
+ return false;
+ }
+ return OP::template Merge( rhs );
+ }
+
+ PointerType operator->()
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator->();
+ }
+
+ ConstPointerType operator->() const
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator->();
+ }
+
+ ReferenceType operator*()
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator*();
+ }
+
+ ConstReferenceType operator*() const
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator*();
+ }
+
+ bool operator!() const // Enables "if (!sp) ..."
+ { return GetImpl(*this) == 0; }
+
+ static inline T * GetPointer( const SmartPtr & sp )
+ { return GetImpl( sp ); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
+ { return GetImpl(*this) == GetImpl(rhs); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
+ { return !(*this == rhs); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
+ { return GetImpl(*this) < GetImpl(rhs); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ return ( GetImpl( rhs ) < GetImpl( *this ) );
+ }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ return !( GetImpl( rhs ) < GetImpl( *this ) );
+ }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ return !( GetImpl( *this ) < GetImpl( rhs ) );
+ }
+
+ private:
+ // Helper for enabling 'if (sp)'
+ struct Tester
+ {
+ Tester(int) {}
+ void dummy() {}
+ };
+
+ typedef void (Tester::*unspecified_boolean_type_)();
+
+ typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
+ unspecified_boolean_type;
+
+ public:
+ // enable 'if (sp)'
+ operator unspecified_boolean_type() const
+ {
+ return !*this ? 0 : &Tester::dummy;
+ }
+
+ private:
+ // Helper for disallowing automatic conversion
+ struct Insipid
+ {
+ Insipid(PointerType) {}
+ };
+
+ typedef typename Select<CP::allow, PointerType, Insipid>::Result
+ AutomaticConversionResult;
+
+ public:
+ operator AutomaticConversionResult() const
+ { return GetImpl(*this); }
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// friends
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP
+ >
+ inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
+ typename SP<T>::StoredType& p)
+ {
+ p = GetImplRef(sp);
+ GetImplRef(sp) = SP<T>::Default();
+ }
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP
+ >
+ inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
+ typename SP<T>::StoredType p)
+ { SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp); }
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// free comparison operators for class template SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator== for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP1,
+ typename U
+ >
+ inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs,
+ U* rhs)
+ { return GetImpl(lhs) == rhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator== for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP1,
+ typename U
+ >
+ inline bool operator==(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs)
+ { return rhs == lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator!= for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return !(lhs == rhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator!= for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator!=(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return rhs != lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator< for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ {
+ return ( GetImpl( lhs ) < rhs );
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator< for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ {
+ return ( GetImpl( rhs ) < lhs );
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// operator> for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return rhs < lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator> for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return rhs < lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator<= for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return !(rhs < lhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator<= for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<=(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return !(rhs < lhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator>= for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return !(lhs < rhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator>= for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>=(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return !(lhs < rhs); }
+
+} // namespace Loki
+
+////////////////////////////////////////////////////////////////////////////////
+/// specialization of std::less for SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+namespace std
+{
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP
+ >
+ struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > >
+ : public binary_function<Loki::SmartPtr<T, OP, CP, KP, SP, CNP >,
+ Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool>
+ {
+ bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const
+ { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
+ };
+}
+
+#endif // end file guardian
+
bgstack15