2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The Loki Library
|
|
|
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
|
|
|
// This code accompanies the book:
|
2008-11-10 05:55:12 +00:00
|
|
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
2002-08-11 05:49:45 +00:00
|
|
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
2011-09-23 00:46:21 +00:00
|
|
|
// Code covered by the MIT License
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
// SOFTWARE.
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2006-10-17 19:48:40 +00:00
|
|
|
#ifndef LOKI_SMARTPTR_INC_
|
|
|
|
#define LOKI_SMARTPTR_INC_
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-10-17 18:48:47 +00:00
|
|
|
// $Id$
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \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
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2010-04-19 03:09:59 +00:00
|
|
|
#include <loki/LokiExport.h>
|
|
|
|
#include <loki/SmallObj.h>
|
|
|
|
#include <loki/TypeManip.h>
|
|
|
|
#include <loki/static_check.h>
|
|
|
|
#include <loki/RefToValue.h>
|
|
|
|
#include <loki/ConstPolicy.h>
|
2006-02-14 11:54:46 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
#include <functional>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <cassert>
|
2006-07-07 09:50:30 +00:00
|
|
|
#include <string>
|
2006-03-17 22:52:56 +00:00
|
|
|
|
|
|
|
#if !defined(_MSC_VER)
|
2008-07-15 20:28:06 +00:00
|
|
|
# if defined(__sparc__)
|
|
|
|
# include <inttypes.h>
|
|
|
|
# else
|
|
|
|
# include <stdint.h>
|
|
|
|
# endif
|
2006-03-17 22:52:56 +00:00
|
|
|
#endif
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-10-17 10:06:58 +00:00
|
|
|
#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
|
|
|
|
|
2010-09-16 17:32:24 +00:00
|
|
|
#if defined( _MSC_VER )
|
|
|
|
#pragma warning( push )
|
|
|
|
#pragma warning( disable: 4355 )
|
|
|
|
#endif
|
|
|
|
|
2006-10-17 10:06:58 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
namespace Loki
|
|
|
|
{
|
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// \class HeapStorage
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerStorageGroup
|
2006-03-27 18:34:36 +00:00
|
|
|
/// Implementation of the StoragePolicy used by SmartPtr. Uses explicit call
|
|
|
|
/// to T's destructor followed by call to free.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
template <class T>
|
|
|
|
class HeapStorage
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
public:
|
2006-11-21 01:34:45 +00:00
|
|
|
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*
|
2006-03-27 18:34:36 +00:00
|
|
|
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2008-11-10 05:55:12 +00:00
|
|
|
HeapStorage() : pointee_(Default())
|
2006-03-27 18:34:36 +00:00
|
|
|
{}
|
|
|
|
|
2008-11-10 05:55:12 +00:00
|
|
|
// The storage policy doesn't initialize the stored pointer
|
2006-03-27 18:34:36 +00:00
|
|
|
// which will be initialized by the OwnershipPolicy's Clone fn
|
|
|
|
HeapStorage(const HeapStorage&) : pointee_(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
template <class U>
|
|
|
|
HeapStorage(const HeapStorage<U>&) : pointee_(0)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2009-09-26 20:27:34 +00:00
|
|
|
explicit HeapStorage(const StoredType& p) : pointee_(p) {}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
PointerType operator->() const { return pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
ReferenceType operator*() const { return *pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
void Swap(HeapStorage& rhs)
|
|
|
|
{ std::swap(pointee_, rhs.pointee_); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
// Accessors
|
2006-10-11 10:44:21 +00:00
|
|
|
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);
|
2006-03-27 18:34:36 +00:00
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
template <class F>
|
|
|
|
friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp);
|
2006-03-27 18:34:36 +00:00
|
|
|
|
|
|
|
// Destroys the data stored
|
|
|
|
// (Destruction might be taken over by the OwnershipPolicy)
|
|
|
|
void Destroy()
|
|
|
|
{
|
2006-03-27 18:38:30 +00:00
|
|
|
if ( 0 != pointee_ )
|
|
|
|
{
|
|
|
|
pointee_->~T();
|
|
|
|
::free( pointee_ );
|
|
|
|
}
|
2006-03-27 18:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default value to initialize the pointer
|
|
|
|
static StoredType Default()
|
|
|
|
{ return 0; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-03-27 18:34:36 +00:00
|
|
|
private:
|
|
|
|
// Data
|
|
|
|
StoredType pointee_;
|
|
|
|
};
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
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_; }
|
|
|
|
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class DefaultSPStorage
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerStorageGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the StoragePolicy used by SmartPtr
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class T>
|
|
|
|
class DefaultSPStorage
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
public:
|
2002-08-11 05:49:45 +00:00
|
|
|
typedef T* StoredType; // the type of the pointee_ object
|
2006-11-21 01:34:45 +00:00
|
|
|
typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
|
2002-08-11 05:49:45 +00:00
|
|
|
typedef T* PointerType; // type returned by operator->
|
|
|
|
typedef T& ReferenceType; // type returned by operator*
|
2003-02-02 16:35:14 +00:00
|
|
|
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2008-11-10 05:55:12 +00:00
|
|
|
DefaultSPStorage() : pointee_(Default())
|
2002-08-11 05:49:45 +00:00
|
|
|
{}
|
|
|
|
|
2008-11-10 05:55:12 +00:00
|
|
|
// The storage policy doesn't initialize the stored pointer
|
2002-08-11 05:49:45 +00:00
|
|
|
// which will be initialized by the OwnershipPolicy's Clone fn
|
2006-01-18 17:21:31 +00:00
|
|
|
DefaultSPStorage(const DefaultSPStorage&) : pointee_(0)
|
2002-08-11 05:49:45 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
template <class U>
|
2006-01-18 17:21:31 +00:00
|
|
|
DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
|
2002-08-11 05:49:45 +00:00
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2009-09-26 20:27:34 +00:00
|
|
|
explicit DefaultSPStorage(const StoredType& p) : pointee_(p) {}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
PointerType operator->() const { return pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
ReferenceType operator*() const { return *pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
void Swap(DefaultSPStorage& rhs)
|
|
|
|
{ std::swap(pointee_, rhs.pointee_); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
// Accessors
|
2006-10-11 10:44:21 +00:00
|
|
|
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);
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
template <class F>
|
|
|
|
friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp);
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
// Destroys the data stored
|
|
|
|
// (Destruction might be taken over by the OwnershipPolicy)
|
2009-11-10 19:22:16 +00:00
|
|
|
//
|
|
|
|
// If your compiler gives you a warning in this area while
|
|
|
|
// compiling the tests, it is on purpose, please ignore it.
|
2002-08-11 05:49:45 +00:00
|
|
|
void Destroy()
|
2006-03-17 22:52:56 +00:00
|
|
|
{
|
|
|
|
delete pointee_;
|
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
// Default value to initialize the pointer
|
|
|
|
static StoredType Default()
|
|
|
|
{ return 0; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
private:
|
|
|
|
// Data
|
|
|
|
StoredType pointee_;
|
|
|
|
};
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
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_; }
|
|
|
|
|
2006-11-21 01:34:45 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// \class LockedStorage
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerStorageGroup
|
2006-11-21 01:34:45 +00:00
|
|
|
/// Implementation of the StoragePolicy used by SmartPtr.
|
2006-11-29 19:16:39 +00:00
|
|
|
///
|
|
|
|
/// 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.
|
2006-11-21 01:34:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-11-29 19:16:39 +00:00
|
|
|
template <class T>
|
2006-12-15 01:36:29 +00:00
|
|
|
class Locker
|
2006-11-29 19:16:39 +00:00
|
|
|
{
|
|
|
|
public:
|
2009-09-26 20:27:34 +00:00
|
|
|
explicit Locker( const T * p ) : pointee_( const_cast< T * >( p ) )
|
2006-12-15 01:36:29 +00:00
|
|
|
{
|
|
|
|
if ( pointee_ != 0 )
|
|
|
|
pointee_->Lock();
|
|
|
|
}
|
2006-11-29 19:16:39 +00:00
|
|
|
|
2006-12-15 01:36:29 +00:00
|
|
|
~Locker( void )
|
2006-11-21 01:34:45 +00:00
|
|
|
{
|
2006-12-15 01:36:29 +00:00
|
|
|
if ( pointee_ != 0 )
|
|
|
|
pointee_->Unlock();
|
|
|
|
}
|
2006-11-21 01:34:45 +00:00
|
|
|
|
2006-12-15 01:36:29 +00:00
|
|
|
operator T * ()
|
|
|
|
{
|
|
|
|
return pointee_;
|
|
|
|
}
|
2006-11-21 01:34:45 +00:00
|
|
|
|
2006-12-15 01:36:29 +00:00
|
|
|
T * operator->()
|
|
|
|
{
|
|
|
|
return pointee_;
|
|
|
|
}
|
2006-11-21 01:34:45 +00:00
|
|
|
|
2006-12-15 01:36:29 +00:00
|
|
|
private:
|
|
|
|
Locker( void );
|
|
|
|
Locker & operator = ( const Locker & );
|
|
|
|
T * pointee_;
|
|
|
|
};
|
2006-11-21 01:34:45 +00:00
|
|
|
|
2006-12-15 01:36:29 +00:00
|
|
|
template <class T>
|
|
|
|
class LockedStorage
|
|
|
|
{
|
|
|
|
public:
|
2006-11-21 01:34:45 +00:00
|
|
|
|
|
|
|
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*
|
|
|
|
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2006-11-21 01:34:45 +00:00
|
|
|
LockedStorage() : pointee_( Default() ) {}
|
|
|
|
|
|
|
|
~LockedStorage( void ) {}
|
|
|
|
|
|
|
|
LockedStorage( const LockedStorage&) : pointee_( 0 ) {}
|
|
|
|
|
2009-09-26 20:27:34 +00:00
|
|
|
explicit LockedStorage( const StoredType & p ) : pointee_( p ) {}
|
2006-11-21 01:34:45 +00:00
|
|
|
|
2009-09-26 20:43:11 +00:00
|
|
|
PointerType operator->() const
|
2006-11-21 01:34:45 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
// 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_; }
|
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
namespace Private
|
|
|
|
{
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// \class DeleteArrayBase
|
|
|
|
///
|
|
|
|
/// \ingroup StrongPointerDeleteGroup
|
|
|
|
/// Base class used only by the DeleteArray policy class. This stores the
|
|
|
|
/// number of elements in an array of shared objects.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class DeleteArrayBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
inline size_t GetArrayCount( void ) const { return m_itemCount; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
DeleteArrayBase( void ) : m_itemCount( 0 ) {}
|
|
|
|
|
|
|
|
explicit DeleteArrayBase( size_t itemCount ) : m_itemCount( itemCount ) {}
|
|
|
|
|
|
|
|
DeleteArrayBase( const DeleteArrayBase & that ) : m_itemCount( that.m_itemCount ) {}
|
|
|
|
|
|
|
|
void Swap( DeleteArrayBase & rhs );
|
|
|
|
|
|
|
|
void OnInit( const void * p ) const;
|
|
|
|
|
|
|
|
void OnCheckRange( size_t index ) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
size_t m_itemCount;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-11-21 01:34:45 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// \class ArrayStorage
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerStorageGroup
|
2006-01-30 20:01:37 +00:00
|
|
|
/// Implementation of the ArrayStorage used by SmartPtr
|
2011-09-21 23:24:54 +00:00
|
|
|
/// This assumes the pointer points to the zeroth element in an array, and uses
|
|
|
|
/// the array-delete operator to deconstruct and deallocate the array. DeepCopy
|
|
|
|
/// is not compatible with ArrayStorage DeepCopy::Clone will only copy the first
|
|
|
|
/// element in the array and won't know the size of the array. Even if it did
|
|
|
|
/// know the size, it would need to use array new to safely work the array
|
|
|
|
/// delete operator in ArrayStorage, but array new will not copy the elements
|
|
|
|
/// in the source array since it calls the default constructor for each element.
|
2006-01-30 20:01:37 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
|
2006-01-30 20:07:38 +00:00
|
|
|
template <class T>
|
2011-09-20 22:33:34 +00:00
|
|
|
class ArrayStorage : public ::Loki::Private::DeleteArrayBase
|
2006-01-30 20:01:37 +00:00
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
public:
|
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
typedef T* StoredType; // the type of the pointee_ object
|
2006-11-21 01:34:45 +00:00
|
|
|
typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
|
2006-01-30 20:01:37 +00:00
|
|
|
typedef T* PointerType; // type returned by operator->
|
|
|
|
typedef T& ReferenceType; // type returned by operator*
|
|
|
|
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
ArrayStorage() : DeleteArrayBase(), pointee_(Default())
|
2006-01-30 20:01:37 +00:00
|
|
|
{}
|
|
|
|
|
2008-11-10 05:55:12 +00:00
|
|
|
// The storage policy doesn't initialize the stored pointer
|
2006-01-30 20:01:37 +00:00
|
|
|
// which will be initialized by the OwnershipPolicy's Clone fn
|
2011-09-20 22:33:34 +00:00
|
|
|
ArrayStorage( const ArrayStorage & that ) : DeleteArrayBase( that ), pointee_( 0 )
|
2006-01-30 20:01:37 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
template <class U>
|
2011-09-20 22:33:34 +00:00
|
|
|
ArrayStorage( const ArrayStorage< U >& that ) : DeleteArrayBase( that ), pointee_( 0 )
|
2006-01-30 20:01:37 +00:00
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
ArrayStorage( const StoredType & p, size_t count ) : DeleteArrayBase( count ),
|
|
|
|
pointee_( p ) {}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
PointerType operator->() const { return pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
ReferenceType operator*() const { return *pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
void Swap( ArrayStorage & rhs )
|
|
|
|
{
|
|
|
|
DeleteArrayBase::Swap( rhs );
|
|
|
|
::std::swap( pointee_, rhs.pointee_ );
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
// Accessors
|
2006-10-11 10:44:21 +00:00
|
|
|
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);
|
2006-01-30 20:01:37 +00:00
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
template <class F>
|
|
|
|
friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp);
|
2006-01-30 20:01:37 +00:00
|
|
|
|
|
|
|
// Destroys the data stored
|
|
|
|
// (Destruction might be taken over by the OwnershipPolicy)
|
|
|
|
void Destroy()
|
|
|
|
{ delete [] pointee_; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
// Default value to initialize the pointer
|
|
|
|
static StoredType Default()
|
|
|
|
{ return 0; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
private:
|
|
|
|
// Data
|
|
|
|
StoredType pointee_;
|
|
|
|
};
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
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_; }
|
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class RefCounted
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
|
|
|
/// Provides a classic external reference counting implementation
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
class RefCounted
|
|
|
|
{
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2008-11-10 05:55:12 +00:00
|
|
|
RefCounted()
|
2006-01-27 08:58:17 +00:00
|
|
|
: pCount_(static_cast<uintptr_t*>(
|
|
|
|
SmallObject<>::operator new(sizeof(uintptr_t))))
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2006-01-27 08:58:17 +00:00
|
|
|
assert(pCount_!=0);
|
2002-08-11 05:49:45 +00:00
|
|
|
*pCount_ = 1;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
|
|
|
RefCounted(const RefCounted& rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
: pCount_(rhs.pCount_)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
// MWCW lacks template friends, hence the following kludge
|
|
|
|
template <typename P1>
|
2008-11-10 05:55:12 +00:00
|
|
|
RefCounted(const RefCounted<P1>& rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
P Clone(const P& val)
|
|
|
|
{
|
|
|
|
++*pCount_;
|
|
|
|
return val;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
bool Release(const P&)
|
|
|
|
{
|
|
|
|
if (!--*pCount_)
|
|
|
|
{
|
2006-01-27 08:58:17 +00:00
|
|
|
SmallObject<>::operator delete(pCount_, sizeof(uintptr_t));
|
2006-02-25 01:52:17 +00:00
|
|
|
pCount_ = NULL;
|
2002-08-11 05:49:45 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
void Swap(RefCounted& rhs)
|
|
|
|
{ std::swap(pCount_, rhs.pCount_); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { destructiveCopy = false };
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Data
|
2006-01-27 08:58:17 +00:00
|
|
|
uintptr_t* pCount_;
|
2002-08-11 05:49:45 +00:00
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct RefCountedMT
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
|
|
|
/// Implements external reference counting for multithreaded programs
|
|
|
|
/// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
|
2006-05-30 14:30:19 +00:00
|
|
|
///
|
|
|
|
/// \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
|
2007-05-01 16:22:02 +00:00
|
|
|
/// 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.
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-22 13:31:45 +00:00
|
|
|
template <template <class, class> class ThreadingModel,
|
2006-01-30 20:07:38 +00:00
|
|
|
class MX = LOKI_DEFAULT_MUTEX >
|
2003-02-27 20:09:08 +00:00
|
|
|
struct RefCountedMTAdj
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2003-02-27 20:09:08 +00:00
|
|
|
template <class P>
|
2006-01-22 13:31:45 +00:00
|
|
|
class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX >
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
public:
|
|
|
|
|
2006-01-22 13:31:45 +00:00
|
|
|
typedef ThreadingModel< RefCountedMT<P>, MX > base_type;
|
2003-02-27 20:09:08 +00:00
|
|
|
typedef typename base_type::IntType CountType;
|
|
|
|
typedef volatile CountType *CountPtrType;
|
|
|
|
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2008-11-10 05:55:12 +00:00
|
|
|
RefCountedMT()
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2003-02-27 20:09:08 +00:00
|
|
|
pCount_ = static_cast<CountPtrType>(
|
2005-12-17 13:15:30 +00:00
|
|
|
SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new(
|
2003-02-27 20:09:08 +00:00
|
|
|
sizeof(*pCount_)));
|
|
|
|
assert(pCount_);
|
2005-08-27 09:21:02 +00:00
|
|
|
//*pCount_ = 1;
|
2006-01-22 13:31:45 +00:00
|
|
|
ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
|
2002-08-11 05:49:45 +00:00
|
|
|
}
|
|
|
|
|
2008-11-10 05:55:12 +00:00
|
|
|
RefCountedMT(const RefCountedMT& rhs)
|
2003-02-27 20:09:08 +00:00
|
|
|
: pCount_(rhs.pCount_)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//MWCW lacks template friends, hence the following kludge
|
|
|
|
template <typename P1>
|
2008-11-10 05:55:12 +00:00
|
|
|
RefCountedMT(const RefCountedMT<P1>& rhs)
|
2003-02-27 20:09:08 +00:00
|
|
|
: pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
|
|
|
|
{}
|
|
|
|
|
|
|
|
P Clone(const P& val)
|
|
|
|
{
|
2006-01-22 13:31:45 +00:00
|
|
|
ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_);
|
2003-02-27 20:09:08 +00:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Release(const P&)
|
|
|
|
{
|
2008-11-10 05:55:12 +00:00
|
|
|
bool isZero = false;
|
|
|
|
ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero );
|
|
|
|
if ( isZero )
|
2003-02-27 20:09:08 +00:00
|
|
|
{
|
2005-12-17 13:15:30 +00:00
|
|
|
SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete(
|
2008-11-10 05:55:12 +00:00
|
|
|
const_cast<CountType *>(pCount_),
|
2003-02-27 20:09:08 +00:00
|
|
|
sizeof(*pCount_));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Swap(RefCountedMT& rhs)
|
|
|
|
{ std::swap(pCount_, rhs.pCount_); }
|
|
|
|
|
|
|
|
enum { destructiveCopy = false };
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Data
|
|
|
|
CountPtrType pCount_;
|
|
|
|
};
|
2002-08-11 05:49:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class COMRefCounted
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
|
|
|
/// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
class COMRefCounted
|
|
|
|
{
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2002-08-11 05:49:45 +00:00
|
|
|
COMRefCounted()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class U>
|
|
|
|
COMRefCounted(const COMRefCounted<U>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static P Clone(const P& val)
|
|
|
|
{
|
2005-10-21 14:17:46 +00:00
|
|
|
if(val!=0)
|
|
|
|
val->AddRef();
|
2002-08-11 05:49:45 +00:00
|
|
|
return val;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static bool Release(const P& val)
|
2008-11-10 05:55:12 +00:00
|
|
|
{
|
|
|
|
if(val!=0)
|
|
|
|
val->Release();
|
|
|
|
return false;
|
2005-10-21 14:17:46 +00:00
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { destructiveCopy = false };
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void Swap(COMRefCounted&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct DeepCopy
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
2008-11-10 05:55:12 +00:00
|
|
|
/// Implements deep copy semantics, assumes existence of a Clone() member
|
2011-09-21 23:24:54 +00:00
|
|
|
/// function of the pointee type. DeepCopy is not compatible with ArrayStorage
|
|
|
|
/// DeepCopy::Clone will only copy the first element in the array and won't
|
|
|
|
/// know the size of the array. Even if it did know the size, it would need to
|
|
|
|
/// use array new to safely work the array delete operator in ArrayStorage, but
|
|
|
|
/// array new will not copy the elements in the source array since it calls the
|
|
|
|
/// default constructor for each array element.
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct DeepCopy
|
|
|
|
{
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2002-08-11 05:49:45 +00:00
|
|
|
DeepCopy()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
DeepCopy(const DeepCopy<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static P Clone(const P& val)
|
|
|
|
{ return val->Clone(); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-02-25 01:52:17 +00:00
|
|
|
static bool Release(const P&)
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return true; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void Swap(DeepCopy&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { destructiveCopy = false };
|
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class RefLinked
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
|
|
|
/// Implements reference linking
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
namespace Private
|
|
|
|
{
|
2006-02-27 19:59:20 +00:00
|
|
|
class LOKI_EXPORT RefLinkedBase
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
2010-09-16 17:32:24 +00:00
|
|
|
RefLinkedBase( void ) :
|
|
|
|
prev_( this ), next_( this )
|
|
|
|
{}
|
2006-02-08 18:12:29 +00:00
|
|
|
|
2006-02-25 01:52:17 +00:00
|
|
|
RefLinkedBase(const RefLinkedBase& rhs);
|
|
|
|
|
|
|
|
bool Release();
|
|
|
|
|
|
|
|
void Swap(RefLinkedBase& rhs);
|
|
|
|
|
2006-03-17 22:52:56 +00:00
|
|
|
bool Merge( RefLinkedBase & rhs );
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { destructiveCopy = false };
|
|
|
|
|
|
|
|
private:
|
2006-03-17 22:52:56 +00:00
|
|
|
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;
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
mutable const RefLinkedBase* prev_;
|
|
|
|
mutable const RefLinkedBase* next_;
|
|
|
|
};
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P>
|
|
|
|
class RefLinked : public Private::RefLinkedBase
|
|
|
|
{
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2002-08-11 05:49:45 +00:00
|
|
|
RefLinked()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
2008-11-10 05:55:12 +00:00
|
|
|
RefLinked(const RefLinked<P1>& rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
: Private::RefLinkedBase(rhs)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static P Clone(const P& val)
|
|
|
|
{ return val; }
|
|
|
|
|
|
|
|
bool Release(const P&)
|
|
|
|
{ return Private::RefLinkedBase::Release(); }
|
2006-03-17 22:52:56 +00:00
|
|
|
|
|
|
|
template < class P1 >
|
|
|
|
bool Merge( RefLinked< P1 > & rhs )
|
|
|
|
{
|
|
|
|
return Private::RefLinkedBase::Merge( rhs );
|
|
|
|
}
|
2002-08-11 05:49:45 +00:00
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class DestructiveCopy
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
|
|
|
/// Implements destructive copy semantics (a la std::auto_ptr)
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
class DestructiveCopy
|
|
|
|
{
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2002-08-11 05:49:45 +00:00
|
|
|
DestructiveCopy()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
DestructiveCopy(const DestructiveCopy<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-17 02:19:01 +00:00
|
|
|
template <class P1>
|
|
|
|
static P Clone( const P1 & val )
|
|
|
|
{
|
|
|
|
P result(val);
|
|
|
|
const_cast< P1 & >( val ) = P1();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
static P Clone(P1& val)
|
|
|
|
{
|
|
|
|
P result(val);
|
|
|
|
val = P1();
|
|
|
|
return result;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static bool Release(const P&)
|
|
|
|
{ return true; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void Swap(DestructiveCopy&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { destructiveCopy = true };
|
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class NoCopy
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerOwnershipGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the OwnershipPolicy used by SmartPtr
|
|
|
|
/// Implements a policy that doesn't allow copying objects
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
class NoCopy
|
|
|
|
{
|
2009-10-07 00:28:23 +00:00
|
|
|
protected:
|
2002-08-11 05:49:45 +00:00
|
|
|
NoCopy()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
NoCopy(const NoCopy<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static P Clone(const P&)
|
|
|
|
{
|
2003-02-02 16:35:14 +00:00
|
|
|
// Make it depended on template parameter
|
|
|
|
static const bool DependedFalse = sizeof(P*) == 0;
|
|
|
|
|
2005-09-26 07:33:05 +00:00
|
|
|
LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
|
2002-08-11 05:49:45 +00:00
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static bool Release(const P&)
|
|
|
|
{ return true; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void Swap(NoCopy&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { destructiveCopy = false };
|
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct AllowConversion
|
2008-11-10 05:55:12 +00:00
|
|
|
///
|
|
|
|
/// \ingroup SmartPointerConversionGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the ConversionPolicy used by SmartPtr
|
|
|
|
/// Allows implicit conversion from SmartPtr to the pointee type
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct AllowConversion
|
|
|
|
{
|
|
|
|
enum { allow = true };
|
|
|
|
|
|
|
|
void Swap(AllowConversion&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct DisallowConversion
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerConversionGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// 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
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct DisallowConversion
|
|
|
|
{
|
|
|
|
DisallowConversion()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
DisallowConversion(const AllowConversion&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
enum { allow = false };
|
|
|
|
|
|
|
|
void Swap(DisallowConversion&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct NoCheck
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerCheckingGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the CheckingPolicy used by SmartPtr
|
|
|
|
/// Well, it's clear what it does :o)
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct NoCheck
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
NoCheck()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
NoCheck( const NoCheck & ) {}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
NoCheck(const NoCheck<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnDefault(const P&)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static void OnInit(const P&)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static void OnDereference(const P&)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static void Swap(NoCheck&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct AssertCheck
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerCheckingGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the CheckingPolicy used by SmartPtr
|
|
|
|
/// Checks the pointer before dereference
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct AssertCheck
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
AssertCheck()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
AssertCheck( const AssertCheck & ) {}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
AssertCheck(const AssertCheck<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
AssertCheck(const NoCheck<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnDefault(const P&)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static void OnInit(const P&)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static void OnDereference(P val)
|
2003-02-27 20:09:08 +00:00
|
|
|
{ assert(val); (void)val; }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
static void Swap(AssertCheck&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct AssertCheckStrict
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerCheckingGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the CheckingPolicy used by SmartPtr
|
|
|
|
/// Checks the pointer against zero upon initialization and before dereference
|
2008-11-10 05:55:12 +00:00
|
|
|
/// You can initialize an AssertCheckStrict with an AssertCheck
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct AssertCheckStrict
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
AssertCheckStrict()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
AssertCheckStrict( const AssertCheckStrict & ) {}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class U>
|
|
|
|
AssertCheckStrict(const AssertCheckStrict<U>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class U>
|
|
|
|
AssertCheckStrict(const AssertCheck<U>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
AssertCheckStrict(const NoCheck<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnDefault(P val)
|
|
|
|
{ assert(val); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnInit(P val)
|
|
|
|
{ assert(val); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnDereference(P val)
|
|
|
|
{ assert(val); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void Swap(AssertCheckStrict&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct NullPointerException
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Used by some implementations of the CheckingPolicy used by SmartPtr
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct NullPointerException : public std::runtime_error
|
|
|
|
{
|
2006-07-07 09:50:30 +00:00
|
|
|
NullPointerException() : std::runtime_error(std::string(""))
|
2002-08-11 05:49:45 +00:00
|
|
|
{ }
|
2002-08-15 02:43:10 +00:00
|
|
|
const char* what() const throw()
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return "Null Pointer Exception"; }
|
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct RejectNullStatic
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerCheckingGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the CheckingPolicy used by SmartPtr
|
|
|
|
/// Checks the pointer upon initialization and before dereference
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct RejectNullStatic
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
RejectNullStatic()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
RejectNullStatic( const RejectNullStatic & ) {}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNullStatic(const RejectNullStatic<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNullStatic(const NoCheck<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNullStatic(const AssertCheck<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNullStatic(const AssertCheckStrict<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnDefault(const P&)
|
|
|
|
{
|
2003-02-02 16:35:14 +00:00
|
|
|
// Make it depended on template parameter
|
2011-09-07 22:46:37 +00:00
|
|
|
static const bool DependedFalse = ( sizeof(P*) == 0 );
|
2003-02-02 16:35:14 +00:00
|
|
|
|
2005-09-26 07:33:05 +00:00
|
|
|
LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
|
2002-08-11 05:49:45 +00:00
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnInit(const P& val)
|
|
|
|
{ if (!val) throw NullPointerException(); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnDereference(const P& val)
|
|
|
|
{ if (!val) throw NullPointerException(); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void Swap(RejectNullStatic&)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct RejectNull
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerCheckingGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the CheckingPolicy used by SmartPtr
|
|
|
|
/// Checks the pointer before dereference
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct RejectNull
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
RejectNull()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
RejectNull( const RejectNull & ) {}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNull(const RejectNull<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-02-28 16:55:56 +00:00
|
|
|
static void OnInit(P)
|
2006-02-28 12:59:59 +00:00
|
|
|
{}
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-02-28 16:55:56 +00:00
|
|
|
static void OnDefault(P)
|
2006-02-28 12:59:59 +00:00
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
void OnDereference(P val)
|
2006-02-28 16:55:56 +00:00
|
|
|
{ if (!val) throw NullPointerException(); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-02-25 13:01:40 +00:00
|
|
|
void OnDereference(P val) const
|
2006-02-28 16:55:56 +00:00
|
|
|
{ if (!val) throw NullPointerException(); }
|
2006-02-25 13:01:40 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
void Swap(RejectNull&)
|
2008-11-10 05:55:12 +00:00
|
|
|
{}
|
2002-08-11 05:49:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \struct RejectNullStrict
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerCheckingGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
/// Implementation of the CheckingPolicy used by SmartPtr
|
|
|
|
/// Checks the pointer upon initialization and before dereference
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template <class P>
|
|
|
|
struct RejectNullStrict
|
|
|
|
{
|
2009-10-07 00:41:02 +00:00
|
|
|
protected:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
RejectNullStrict()
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
RejectNullStrict( const RejectNullStrict & ) {}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNullStrict(const RejectNullStrict<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template <class P1>
|
|
|
|
RejectNullStrict(const RejectNull<P1>&)
|
|
|
|
{}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
static void OnInit(P val)
|
|
|
|
{ if (!val) throw NullPointerException(); }
|
|
|
|
|
|
|
|
void OnDereference(P val)
|
|
|
|
{ OnInit(val); }
|
2006-02-25 13:01:40 +00:00
|
|
|
|
|
|
|
void OnDereference(P val) const
|
|
|
|
{ OnInit(val); }
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
void Swap(RejectNullStrict&)
|
2008-11-10 05:55:12 +00:00
|
|
|
{}
|
2002-08-11 05:49:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template SmartPtr (declaration)
|
|
|
|
// The reason for all the fuss above
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-01-30 20:07:38 +00:00
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OwnershipPolicy = RefCounted,
|
|
|
|
class ConversionPolicy = DisallowConversion,
|
|
|
|
template <class> class CheckingPolicy = AssertCheck,
|
|
|
|
template <class> class StoragePolicy = DefaultSPStorage,
|
2008-11-10 05:55:12 +00:00
|
|
|
template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
|
2006-01-30 20:07:38 +00:00
|
|
|
>
|
|
|
|
class SmartPtr;
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2003-02-27 20:09:08 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// class template SmartPtrDef (definition)
|
2008-11-10 05:55:12 +00:00
|
|
|
// this class added to unify the usage of SmartPtr
|
2003-02-27 20:09:08 +00:00
|
|
|
// 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,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class StoragePolicy = DefaultSPStorage,
|
2008-11-10 05:55:12 +00:00
|
|
|
template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
|
2003-02-27 20:09:08 +00:00
|
|
|
>
|
|
|
|
struct SmartPtrDef
|
|
|
|
{
|
|
|
|
typedef SmartPtr
|
|
|
|
<
|
|
|
|
T,
|
|
|
|
OwnershipPolicy,
|
|
|
|
ConversionPolicy,
|
|
|
|
CheckingPolicy,
|
2006-02-25 13:48:54 +00:00
|
|
|
StoragePolicy,
|
2006-06-19 12:39:09 +00:00
|
|
|
ConstnessPolicy
|
2003-02-27 20:09:08 +00:00
|
|
|
>
|
|
|
|
type;
|
|
|
|
};
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \class SmartPtr
|
|
|
|
///
|
2008-11-10 05:55:12 +00:00
|
|
|
/// \ingroup SmartPointerGroup
|
2005-11-03 12:43:55 +00:00
|
|
|
///
|
|
|
|
/// \param OwnershipPolicy default = RefCounted,
|
|
|
|
/// \param ConversionPolicy default = DisallowConversion,
|
|
|
|
/// \param CheckingPolicy default = AssertCheck,
|
|
|
|
/// \param StoragePolicy default = DefaultSPStorage
|
2006-02-25 13:48:54 +00:00
|
|
|
/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
|
2005-11-03 12:43:55 +00:00
|
|
|
///
|
|
|
|
/// \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
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OwnershipPolicy,
|
|
|
|
class ConversionPolicy,
|
|
|
|
template <class> class CheckingPolicy,
|
2006-01-30 20:01:37 +00:00
|
|
|
template <class> class StoragePolicy,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class ConstnessPolicy
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
|
|
|
class SmartPtr
|
|
|
|
: public StoragePolicy<T>
|
2006-11-21 01:34:45 +00:00
|
|
|
, public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
|
2002-08-11 05:49:45 +00:00
|
|
|
, public CheckingPolicy<typename StoragePolicy<T>::StoredType>
|
|
|
|
, public ConversionPolicy
|
|
|
|
{
|
|
|
|
typedef StoragePolicy<T> SP;
|
2006-11-21 01:34:45 +00:00
|
|
|
typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
|
2002-08-11 05:49:45 +00:00
|
|
|
typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
|
|
|
|
typedef ConversionPolicy CP;
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
public:
|
2006-01-30 20:07:38 +00:00
|
|
|
typedef typename ConstnessPolicy<T>::Type* ConstPointerType;
|
|
|
|
typedef typename ConstnessPolicy<T>::Type& ConstReferenceType;
|
2006-01-30 20:01:37 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
typedef typename SP::PointerType PointerType;
|
|
|
|
typedef typename SP::StoredType StoredType;
|
|
|
|
typedef typename SP::ReferenceType ReferenceType;
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-02-25 13:48:54 +00:00
|
|
|
typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
|
|
|
|
CopyArg;
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
private:
|
2006-10-20 10:12:15 +00:00
|
|
|
struct NeverMatched {};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
#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
|
|
|
|
|
2009-11-10 19:22:16 +00:00
|
|
|
/// SmartPtr uses this helper class to specify the dynamic-caster constructor.
|
|
|
|
class DynamicCastHelper {};
|
|
|
|
|
|
|
|
/// Private constructor is only used for dynamic-casting.
|
|
|
|
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, const DynamicCastHelper & helper )
|
|
|
|
{
|
|
|
|
(void)helper; // do void cast to remove compiler warning.
|
|
|
|
// Dynamic casting from T1 to T and saving result in `this''s pointer
|
|
|
|
PointerType p = dynamic_cast< PointerType >( GetImplRef( rhs ) );
|
2011-09-07 22:46:37 +00:00
|
|
|
KP::OnDereference( p );
|
2009-11-10 19:22:16 +00:00
|
|
|
GetImplRef( *this ) = OP::Clone( p );
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Private constructor is only used for dynamic-casting.
|
|
|
|
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, const DynamicCastHelper & helper )
|
|
|
|
{
|
|
|
|
(void)helper; // do void cast to remove compiler warning.
|
|
|
|
// Dynamic casting from T1 to T and saving result in `this''s pointer
|
|
|
|
PointerType p = dynamic_cast< PointerType >( GetImplRef( rhs ) );
|
2011-09-07 22:46:37 +00:00
|
|
|
KP::OnDereference( p );
|
2009-11-10 19:22:16 +00:00
|
|
|
GetImplRef( *this ) = OP::Clone( p );
|
|
|
|
}
|
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
public:
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
SmartPtr()
|
2006-11-21 01:34:45 +00:00
|
|
|
{
|
|
|
|
KP::OnDefault(GetImpl(*this));
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
explicit
|
2006-05-17 16:04:32 +00:00
|
|
|
SmartPtr(ExplicitArg p) : SP(p)
|
2006-11-21 01:34:45 +00:00
|
|
|
{
|
|
|
|
KP::OnInit(GetImpl(*this));
|
|
|
|
}
|
2003-08-21 12:55:14 +00:00
|
|
|
|
2006-05-17 16:04:32 +00:00
|
|
|
SmartPtr(ImplicitArg p) : SP(p)
|
2006-11-21 01:34:45 +00:00
|
|
|
{
|
|
|
|
KP::OnInit(GetImpl(*this));
|
|
|
|
}
|
2003-08-21 12:55:14 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
/** This constructor was designed to only work with the ArrayStorage policy. Using it with
|
|
|
|
any other Delete policies will cause compiler errors. Call it with this syntax:
|
|
|
|
"ThingyPtr sp2( new Thingy[ 4 ], 4 );" so SmartPtr can do range checking on the number of elements.
|
|
|
|
*/
|
|
|
|
SmartPtr( ImplicitArg p, size_t itemCount ) : SP( p, itemCount )
|
|
|
|
{
|
|
|
|
KP::OnInit( GetImpl( *this ) );
|
|
|
|
SP::OnInit( GetImpl( *this ) );
|
|
|
|
}
|
|
|
|
|
2006-11-21 01:34:45 +00:00
|
|
|
SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
|
|
|
{
|
2011-09-07 22:46:37 +00:00
|
|
|
KP::OnDereference( GetImpl( rhs ) );
|
2006-11-21 01:34:45 +00:00
|
|
|
GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
|
|
|
|
}
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2011-09-13 00:50:05 +00:00
|
|
|
SmartPtr( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 >& rhs )
|
2003-08-21 12:55:14 +00:00
|
|
|
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
2009-11-10 19:22:16 +00:00
|
|
|
{
|
2011-09-07 22:46:37 +00:00
|
|
|
KP::OnDereference( GetImpl( rhs ) );
|
2009-11-10 19:22:16 +00:00
|
|
|
GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
|
|
|
|
}
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2011-09-13 00:50:05 +00:00
|
|
|
SmartPtr( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 >& rhs )
|
2003-08-21 12:55:14 +00:00
|
|
|
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
2006-11-21 01:34:45 +00:00
|
|
|
{
|
2011-09-07 22:46:37 +00:00
|
|
|
KP::OnDereference( GetImpl( rhs ) );
|
2006-11-21 01:34:45 +00:00
|
|
|
GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
|
|
|
|
}
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-02-14 11:54:46 +00:00
|
|
|
SmartPtr(RefToValue<SmartPtr> rhs)
|
2003-08-21 12:55:14 +00:00
|
|
|
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
2011-09-13 00:50:05 +00:00
|
|
|
{
|
|
|
|
SmartPtr & ref = rhs;
|
|
|
|
KP::OnDereference( GetImpl( ref ) );
|
|
|
|
GetImplRef( *this ) = OP::Clone( GetImplRef( ref ) );
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-02-14 11:54:46 +00:00
|
|
|
operator RefToValue<SmartPtr>()
|
|
|
|
{ return RefToValue<SmartPtr>(*this); }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
SmartPtr& operator=(CopyArg& rhs)
|
|
|
|
{
|
|
|
|
SmartPtr temp(rhs);
|
|
|
|
temp.Swap(*this);
|
|
|
|
return *this;
|
|
|
|
}
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2006-02-25 01:52:17 +00:00
|
|
|
SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
|
2003-08-21 12:55:14 +00:00
|
|
|
{
|
|
|
|
SmartPtr temp(rhs);
|
|
|
|
temp.Swap(*this);
|
|
|
|
return *this;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2006-02-25 01:52:17 +00:00
|
|
|
SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
|
2003-08-21 12:55:14 +00:00
|
|
|
{
|
|
|
|
SmartPtr temp(rhs);
|
|
|
|
temp.Swap(*this);
|
|
|
|
return *this;
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
/** This function is equivalent to an assignment operator for SmartPtr's that use the
|
|
|
|
DeleteArray policy where the programmer needs to write the equivalent of "sp = new P;".
|
|
|
|
With DeleteArray, the programmer should write "sp.Assign( new [5] Thingy, 5 );" so the
|
|
|
|
SmartPtr knows how many elements are in the array.
|
|
|
|
*/
|
|
|
|
SmartPtr & Assign( T * p, size_t itemCount )
|
|
|
|
{
|
|
|
|
if ( GetImpl( *this ) != p )
|
|
|
|
{
|
|
|
|
SmartPtr temp( p, itemCount );
|
|
|
|
Swap( temp );
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
void Swap(SmartPtr& rhs)
|
|
|
|
{
|
|
|
|
OP::Swap(rhs);
|
|
|
|
CP::Swap(rhs);
|
|
|
|
KP::Swap(rhs);
|
|
|
|
SP::Swap(rhs);
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2003-08-21 12:55:14 +00:00
|
|
|
~SmartPtr()
|
|
|
|
{
|
|
|
|
if (OP::Release(GetImpl(*static_cast<SP*>(this))))
|
|
|
|
{
|
|
|
|
SP::Destroy();
|
|
|
|
}
|
|
|
|
}
|
2006-10-11 10:44:21 +00:00
|
|
|
|
2009-11-10 19:22:16 +00:00
|
|
|
/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template < class > class OP1,
|
|
|
|
class CP1,
|
|
|
|
template < class > class KP1,
|
|
|
|
template < class > class SP1,
|
|
|
|
template < class > class CNP1
|
|
|
|
>
|
|
|
|
SmartPtr & DynamicCastFrom( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
|
|
|
|
{
|
|
|
|
SmartPtr temp( rhs, DynamicCastHelper() );
|
|
|
|
temp.Swap( *this );
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template < class > class OP1,
|
|
|
|
class CP1,
|
|
|
|
template < class > class KP1,
|
|
|
|
template < class > class SP1,
|
|
|
|
template < class > class CNP1
|
|
|
|
>
|
|
|
|
SmartPtr & DynamicCastFrom( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
|
|
|
|
{
|
|
|
|
SmartPtr temp( rhs, DynamicCastHelper() );
|
|
|
|
temp.Swap( *this );
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2006-10-17 10:06:58 +00:00
|
|
|
#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();
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-10-17 10:06:58 +00:00
|
|
|
friend inline void Reset(SmartPtr& sp, typename SP::StoredType p)
|
|
|
|
{ SmartPtr(p).Swap(sp); }
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
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,
|
2006-10-17 09:14:27 +00:00
|
|
|
typename SP1<T1>::StoredType& p);
|
2006-10-11 10:44:21 +00:00
|
|
|
|
|
|
|
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,
|
2006-10-17 09:14:27 +00:00
|
|
|
typename SP1<T1>::StoredType p);
|
2006-10-17 10:06:58 +00:00
|
|
|
#endif
|
2006-10-11 10:44:21 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-03-17 22:52:56 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-10-11 10:44:21 +00:00
|
|
|
return OP::template Merge( rhs );
|
2006-03-17 22:52:56 +00:00
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
PointerType operator->()
|
|
|
|
{
|
|
|
|
KP::OnDereference(GetImplRef(*this));
|
|
|
|
return SP::operator->();
|
|
|
|
}
|
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
ConstPointerType operator->() const
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
|
|
|
KP::OnDereference(GetImplRef(*this));
|
|
|
|
return SP::operator->();
|
|
|
|
}
|
|
|
|
|
|
|
|
ReferenceType operator*()
|
|
|
|
{
|
|
|
|
KP::OnDereference(GetImplRef(*this));
|
|
|
|
return SP::operator*();
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2006-01-30 20:01:37 +00:00
|
|
|
ConstReferenceType operator*() const
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
|
|
|
KP::OnDereference(GetImplRef(*this));
|
|
|
|
return SP::operator*();
|
|
|
|
}
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2011-09-20 22:33:34 +00:00
|
|
|
/** operator[] returns a reference to an modifiable object. If the index is greater than or
|
|
|
|
equal to the number of elements, the function will throw a std::out_of_range exception.
|
|
|
|
This only works with DeleteArray policy. Any other policy will cause a compiler error.
|
|
|
|
*/
|
|
|
|
ReferenceType operator [] ( size_t index )
|
|
|
|
{
|
|
|
|
PointerType p = SP::operator->();
|
|
|
|
KP::OnDereference( p );
|
|
|
|
SP::OnCheckRange( index );
|
|
|
|
return p[ index ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/** operator[] returns a reference to a const object. If the index is greater than or
|
|
|
|
equal to the number of elements, the function will throw a std::out_of_range exception.
|
|
|
|
This only works with DeleteArray policy. Any other policy will cause a compiler error.
|
|
|
|
*/
|
|
|
|
ConstReferenceType operator [] ( size_t index ) const
|
|
|
|
{
|
|
|
|
ConstPointerType p = SP::operator->();
|
|
|
|
KP::OnDereference( p );
|
|
|
|
SP::OnCheckRange( index );
|
|
|
|
return p[ index ];
|
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
bool operator!() const // Enables "if (!sp) ..."
|
|
|
|
{ return GetImpl(*this) == 0; }
|
2006-03-17 22:52:56 +00:00
|
|
|
|
|
|
|
static inline T * GetPointer( const SmartPtr & sp )
|
|
|
|
{ return GetImpl( sp ); }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
// Ambiguity buster
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2006-02-25 01:52:17 +00:00
|
|
|
bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
|
2004-03-14 16:41:35 +00:00
|
|
|
{ return GetImpl(*this) == GetImpl(rhs); }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
// Ambiguity buster
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2006-02-25 01:52:17 +00:00
|
|
|
bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return !(*this == rhs); }
|
|
|
|
|
|
|
|
// Ambiguity buster
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T1,
|
|
|
|
template <class> class OP1,
|
|
|
|
class CP1,
|
|
|
|
template <class> class KP1,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP1,
|
|
|
|
template <class> class CNP1
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2006-02-25 01:52:17 +00:00
|
|
|
bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
|
2004-03-14 16:41:35 +00:00
|
|
|
{ return GetImpl(*this) < GetImpl(rhs); }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
2006-03-17 22:52:56 +00:00
|
|
|
// 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 ) );
|
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
private:
|
|
|
|
// Helper for enabling 'if (sp)'
|
|
|
|
struct Tester
|
|
|
|
{
|
2004-03-14 16:41:35 +00:00
|
|
|
Tester(int) {}
|
|
|
|
void dummy() {}
|
2002-08-11 05:49:45 +00:00
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2004-03-14 16:41:35 +00:00
|
|
|
typedef void (Tester::*unspecified_boolean_type_)();
|
|
|
|
|
|
|
|
typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
|
|
|
|
unspecified_boolean_type;
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
public:
|
|
|
|
// enable 'if (sp)'
|
2004-03-14 16:41:35 +00:00
|
|
|
operator unspecified_boolean_type() const
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2004-03-14 16:41:35 +00:00
|
|
|
return !*this ? 0 : &Tester::dummy;
|
2002-08-11 05:49:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Helper for disallowing automatic conversion
|
|
|
|
struct Insipid
|
|
|
|
{
|
|
|
|
Insipid(PointerType) {}
|
|
|
|
};
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
typedef typename Select<CP::allow, PointerType, Insipid>::Result
|
|
|
|
AutomaticConversionResult;
|
2008-11-10 05:55:12 +00:00
|
|
|
|
|
|
|
public:
|
2002-08-11 05:49:45 +00:00
|
|
|
operator AutomaticConversionResult() const
|
|
|
|
{ return GetImpl(*this); }
|
|
|
|
};
|
|
|
|
|
2006-10-16 16:34:48 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// friends
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-10-17 10:06:58 +00:00
|
|
|
#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
|
|
|
|
|
2006-10-11 10:44:21 +00:00
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-10-16 16:34:48 +00:00
|
|
|
template <class> class CNP
|
2006-10-11 10:44:21 +00:00
|
|
|
>
|
2006-10-16 16:34:48 +00:00
|
|
|
inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
|
2006-10-11 10:44:21 +00:00
|
|
|
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,
|
2006-10-16 16:34:48 +00:00
|
|
|
template <class> class CNP
|
2006-10-11 10:44:21 +00:00
|
|
|
>
|
2006-10-16 16:34:48 +00:00
|
|
|
inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
|
2006-10-11 10:44:21 +00:00
|
|
|
typename SP<T>::StoredType p)
|
2006-10-16 16:34:48 +00:00
|
|
|
{ SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp); }
|
2006-10-11 10:44:21 +00:00
|
|
|
|
2006-10-17 10:06:58 +00:00
|
|
|
#endif
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// free comparison operators for class template SmartPtr
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator== for lhs = SmartPtr, rhs = raw pointer
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class CNP1,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2006-02-25 01:52:17 +00:00
|
|
|
inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs,
|
2004-03-14 16:41:35 +00:00
|
|
|
U* rhs)
|
2009-04-11 06:01:06 +00:00
|
|
|
{ return ( GetImpl( lhs ) == rhs ); }
|
2006-03-17 22:52:56 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator== for lhs = raw pointer, rhs = SmartPtr
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class CNP1,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2004-03-14 16:41:35 +00:00
|
|
|
inline bool operator==(U* lhs,
|
2006-02-25 01:52:17 +00:00
|
|
|
const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs)
|
2009-04-11 06:01:06 +00:00
|
|
|
{ return ( GetImpl( rhs ) == lhs ); }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator!= for lhs = SmartPtr, rhs = raw pointer
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2006-02-25 13:48:54 +00:00
|
|
|
inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
|
2004-03-14 16:41:35 +00:00
|
|
|
U* rhs)
|
2009-04-11 06:01:06 +00:00
|
|
|
{ return ( GetImpl( lhs ) != rhs ); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator!= for lhs = raw pointer, rhs = SmartPtr
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2004-03-14 16:41:35 +00:00
|
|
|
inline bool operator!=(U* lhs,
|
2006-02-25 13:48:54 +00:00
|
|
|
const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
|
2009-04-11 06:01:06 +00:00
|
|
|
{ return ( GetImpl( rhs ) != lhs ); }
|
2002-08-11 05:49:45 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2006-03-17 22:52:56 +00:00
|
|
|
/// operator< for lhs = SmartPtr, rhs = raw pointer
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2006-02-25 13:48:54 +00:00
|
|
|
inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
|
2006-03-17 22:52:56 +00:00
|
|
|
U* rhs)
|
|
|
|
{
|
|
|
|
return ( GetImpl( lhs ) < rhs );
|
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2006-03-17 22:52:56 +00:00
|
|
|
/// operator< for lhs = raw pointer, rhs = SmartPtr
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2004-03-14 16:41:35 +00:00
|
|
|
inline bool operator<(U* lhs,
|
2006-03-17 22:52:56 +00:00
|
|
|
const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
|
|
|
|
{
|
2009-04-11 06:01:06 +00:00
|
|
|
return ( lhs < GetImpl( rhs ) );
|
2006-03-17 22:52:56 +00:00
|
|
|
}
|
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2006-03-17 22:52:56 +00:00
|
|
|
// operator> for lhs = SmartPtr, rhs = raw pointer
|
2005-11-03 12:43:55 +00:00
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2006-02-25 13:48:54 +00:00
|
|
|
inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
|
2004-03-14 16:41:35 +00:00
|
|
|
U* rhs)
|
2009-04-11 06:01:06 +00:00
|
|
|
{ return rhs < GetImpl( lhs ); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator> for lhs = raw pointer, rhs = SmartPtr
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2004-03-14 16:41:35 +00:00
|
|
|
inline bool operator>(U* lhs,
|
2006-02-25 13:48:54 +00:00
|
|
|
const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return rhs < lhs; }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator<= for lhs = SmartPtr, rhs = raw pointer
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2006-02-25 13:48:54 +00:00
|
|
|
inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
|
2004-03-14 16:41:35 +00:00
|
|
|
U* rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return !(rhs < lhs); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator<= for lhs = raw pointer, rhs = SmartPtr
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2004-03-14 16:41:35 +00:00
|
|
|
inline bool operator<=(U* lhs,
|
2006-02-25 13:48:54 +00:00
|
|
|
const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return !(rhs < lhs); }
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator>= for lhs = SmartPtr, rhs = raw pointer
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2006-02-25 13:48:54 +00:00
|
|
|
inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
|
2004-03-14 16:41:35 +00:00
|
|
|
U* rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return !(lhs < rhs); }
|
2008-11-10 05:55:12 +00:00
|
|
|
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// operator>= for lhs = raw pointer, rhs = SmartPtr
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP,
|
2002-08-11 05:49:45 +00:00
|
|
|
typename U
|
|
|
|
>
|
2004-03-14 16:41:35 +00:00
|
|
|
inline bool operator>=(U* lhs,
|
2006-02-25 13:48:54 +00:00
|
|
|
const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return !(lhs < rhs); }
|
|
|
|
|
|
|
|
} // namespace Loki
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2005-11-03 12:43:55 +00:00
|
|
|
/// specialization of std::less for SmartPtr
|
|
|
|
/// \ingroup SmartPointerGroup
|
2002-08-11 05:49:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
template
|
|
|
|
<
|
|
|
|
typename T,
|
|
|
|
template <class> class OP,
|
|
|
|
class CP,
|
|
|
|
template <class> class KP,
|
2006-02-25 01:52:17 +00:00
|
|
|
template <class> class SP,
|
2006-02-25 13:48:54 +00:00
|
|
|
template <class> class CNP
|
2002-08-11 05:49:45 +00:00
|
|
|
>
|
2006-02-25 13:48:54 +00:00
|
|
|
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>
|
2002-08-11 05:49:45 +00:00
|
|
|
{
|
2006-02-25 13:48:54 +00:00
|
|
|
bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
|
|
|
|
const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const
|
2002-08-11 05:49:45 +00:00
|
|
|
{ return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-09-16 17:32:24 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2006-10-17 19:30:16 +00:00
|
|
|
|
2010-09-16 17:32:24 +00:00
|
|
|
#if defined( _MSC_VER )
|
|
|
|
#pragma warning( pop )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif // end file guardian
|