]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/SmartPtr.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / SmartPtr.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 //     purpose is hereby granted without fee, provided that the above copyright
9 //     notice appear in all copies and that both that copyright notice and this
10 //     permission notice appear in supporting documentation.
11 // The author or Addison-Wesley Longman make no representations about the
12 //     suitability of this software for any purpose. It is provided "as is"
13 //     without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_SMARTPTR_INC_
16 #define LOKI_SMARTPTR_INC_
17
18 // $Id: SmartPtr.h 903 2008-11-10 05:55:12Z rich_sposato $
19
20
21 ///  \defgroup  SmartPointerGroup Smart pointers
22 ///  Policy based implementation of a smart pointer
23 ///  \defgroup  SmartPointerOwnershipGroup Ownership policies
24 ///  \ingroup   SmartPointerGroup
25 ///  \defgroup  SmartPointerStorageGroup Storage policies
26 ///  \ingroup   SmartPointerGroup
27 ///  \defgroup  SmartPointerConversionGroup Conversion policies
28 ///  \ingroup   SmartPointerGroup
29 ///  \defgroup  SmartPointerCheckingGroup Checking policies
30 ///  \ingroup   SmartPointerGroup
31
32 #include "LokiExport.h"
33 #include "SmallObj.h"
34 #include "TypeManip.h"
35 #include "static_check.h"
36 #include "RefToValue.h"
37 #include "ConstPolicy.h"
38
39 #include <functional>
40 #include <stdexcept>
41 #include <cassert>
42 #include <string>
43
44 #if !defined(_MSC_VER)
45 #  if defined(__sparc__)
46 #    include <inttypes.h>
47 #  else
48 #    include <stdint.h>
49 #  endif
50 #endif
51
52 #if defined(_MSC_VER) || defined(__GNUC__)
53 // GCC>=4.1 must use -ffriend-injection due to a bug in GCC
54 #define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
55 #endif
56
57
58 namespace Loki
59 {
60
61 ////////////////////////////////////////////////////////////////////////////////
62 ///  \class HeapStorage
63 ///
64 ///  \ingroup  SmartPointerStorageGroup
65 ///  Implementation of the StoragePolicy used by SmartPtr.  Uses explicit call
66 ///   to T's destructor followed by call to free.
67 ////////////////////////////////////////////////////////////////////////////////
68
69
70 template <class T>
71 class HeapStorage
72 {
73 public:
74         typedef T *StoredType;      /// the type of the pointee_ object
75         typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
76         typedef T *PointerType;     /// type returned by operator->
77         typedef T &ReferenceType;   /// type returned by operator*
78
79         HeapStorage() : pointee_(Default())
80         {}
81
82         // The storage policy doesn't initialize the stored pointer
83         //     which will be initialized by the OwnershipPolicy's Clone fn
84         HeapStorage(const HeapStorage &) : pointee_(0)
85         {}
86
87         template <class U>
88         HeapStorage(const HeapStorage<U>&) : pointee_(0)
89         {}
90
91         HeapStorage(const StoredType &p) : pointee_(p) {}
92
93         PointerType operator->() const
94         {
95                 return pointee_;
96         }
97
98         ReferenceType operator*() const
99         {
100                 return *pointee_;
101         }
102
103         void Swap(HeapStorage &rhs)
104         {
105                 std::swap(pointee_, rhs.pointee_);
106         }
107
108         // Accessors
109         template <class F>
110         friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp);
111
112         template <class F>
113         friend const typename HeapStorage<F>::StoredType &GetImplRef(const HeapStorage<F>& sp);
114
115         template <class F>
116         friend typename HeapStorage<F>::StoredType &GetImplRef(HeapStorage<F>& sp);
117
118 protected:
119         // Destroys the data stored
120         // (Destruction might be taken over by the OwnershipPolicy)
121         void Destroy()
122         {
123                 if ( 0 != pointee_ )
124                 {
125                         pointee_->~T();
126                         ::free( pointee_ );
127                 }
128         }
129
130         // Default value to initialize the pointer
131         static StoredType Default()
132         {
133                 return 0;
134         }
135
136 private:
137         // Data
138         StoredType pointee_;
139 };
140
141 template <class T>
142 inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp)
143 {
144         return sp.pointee_;
145 }
146
147 template <class T>
148 inline const typename HeapStorage<T>::StoredType &GetImplRef(const HeapStorage<T>& sp)
149 {
150         return sp.pointee_;
151 }
152
153 template <class T>
154 inline typename HeapStorage<T>::StoredType &GetImplRef(HeapStorage<T>& sp)
155 {
156         return sp.pointee_;
157 }
158
159
160 ////////////////////////////////////////////////////////////////////////////////
161 ///  \class DefaultSPStorage
162 ///
163 ///  \ingroup  SmartPointerStorageGroup
164 ///  Implementation of the StoragePolicy used by SmartPtr
165 ////////////////////////////////////////////////////////////////////////////////
166
167
168 template <class T>
169 class DefaultSPStorage
170 {
171 public:
172         typedef T *StoredType;    // the type of the pointee_ object
173         typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
174         typedef T *PointerType;   // type returned by operator->
175         typedef T &ReferenceType; // type returned by operator*
176
177         DefaultSPStorage() : pointee_(Default())
178         {}
179
180         // The storage policy doesn't initialize the stored pointer
181         //     which will be initialized by the OwnershipPolicy's Clone fn
182         DefaultSPStorage(const DefaultSPStorage &) : pointee_(0)
183         {}
184
185         template <class U>
186         DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
187         {}
188
189         DefaultSPStorage(const StoredType &p) : pointee_(p) {}
190
191         PointerType operator->() const
192         {
193                 return pointee_;
194         }
195
196         ReferenceType operator*() const
197         {
198                 return *pointee_;
199         }
200
201         void Swap(DefaultSPStorage &rhs)
202         {
203                 std::swap(pointee_, rhs.pointee_);
204         }
205
206         // Accessors
207         template <class F>
208         friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp);
209
210         template <class F>
211         friend const typename DefaultSPStorage<F>::StoredType &GetImplRef(const DefaultSPStorage<F>& sp);
212
213         template <class F>
214         friend typename DefaultSPStorage<F>::StoredType &GetImplRef(DefaultSPStorage<F>& sp);
215
216 protected:
217         // Destroys the data stored
218         // (Destruction might be taken over by the OwnershipPolicy)
219         //
220         // If your compiler gives you a warning in this area while
221         // compiling the tests, it is on purpose, please ignore it.
222         void Destroy()
223         {
224                 delete pointee_;
225         }
226
227         // Default value to initialize the pointer
228         static StoredType Default()
229         {
230                 return 0;
231         }
232
233 private:
234         // Data
235         StoredType pointee_;
236 };
237
238 template <class T>
239 inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp)
240 {
241         return sp.pointee_;
242 }
243
244 template <class T>
245 inline const typename DefaultSPStorage<T>::StoredType &GetImplRef(const DefaultSPStorage<T>& sp)
246 {
247         return sp.pointee_;
248 }
249
250 template <class T>
251 inline typename DefaultSPStorage<T>::StoredType &GetImplRef(DefaultSPStorage<T>& sp)
252 {
253         return sp.pointee_;
254 }
255
256
257 ////////////////////////////////////////////////////////////////////////////////
258 ///  \class LockedStorage
259 ///
260 ///  \ingroup  SmartPointerStorageGroup
261 ///  Implementation of the StoragePolicy used by SmartPtr.
262 ///
263 ///  Each call to operator-> locks the object for the duration of a call to a
264 ///  member function of T.
265 ///
266 ///  \par How It Works
267 ///  LockedStorage has a helper class called Locker, which acts as a smart
268 ///  pointer with limited abilities.  LockedStorage::operator-> returns an
269 ///  unnamed temporary of type Locker<T> that exists for the duration of the
270 ///  call to a member function of T.  The unnamed temporary locks the object
271 ///  when it is constructed by operator-> and unlocks the object when it is
272 ///  destructed.
273 ///
274 ///  \note This storage policy requires class T to have member functions Lock
275 ///  and Unlock.  If your class does not have Lock or Unlock functions, you may
276 ///  either make a child class which does, or make a policy class similar to
277 ///  LockedStorage which calls other functions to lock the object.
278 ////////////////////////////////////////////////////////////////////////////////
279
280 template <class T>
281 class Locker
282 {
283 public:
284         Locker( const T *p ) : pointee_( const_cast< T * >( p ) )
285         {
286                 if ( pointee_ != 0 )
287                         pointee_->Lock();
288         }
289
290         ~Locker( void )
291         {
292                 if ( pointee_ != 0 )
293                         pointee_->Unlock();
294         }
295
296         operator T *()
297         {
298                 return pointee_;
299         }
300
301         T *operator->()
302         {
303                 return pointee_;
304         }
305
306 private:
307         Locker( void );
308         Locker &operator = ( const Locker & );
309         T *pointee_;
310 };
311
312 template <class T>
313 class LockedStorage
314 {
315 public:
316
317         typedef T *StoredType;           /// the type of the pointee_ object
318         typedef T *InitPointerType;      /// type used to declare OwnershipPolicy type.
319         typedef Locker< T > PointerType; /// type returned by operator->
320         typedef T &ReferenceType;        /// type returned by operator*
321
322         LockedStorage() : pointee_( Default() ) {}
323
324         ~LockedStorage( void ) {}
325
326         LockedStorage( const LockedStorage &) : pointee_( 0 ) {}
327
328         LockedStorage( const StoredType &p ) : pointee_( p ) {}
329
330         PointerType operator->()
331         {
332                 return Locker< T >( pointee_ );
333         }
334
335         void Swap(LockedStorage &rhs)
336         {
337                 std::swap( pointee_, rhs.pointee_ );
338         }
339
340         // Accessors
341         template <class F>
342         friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp);
343
344         template <class F>
345         friend const typename LockedStorage<F>::StoredType &GetImplRef(const LockedStorage<F>& sp);
346
347         template <class F>
348         friend typename LockedStorage<F>::StoredType &GetImplRef(LockedStorage<F>& sp);
349
350 protected:
351         // Destroys the data stored
352         // (Destruction might be taken over by the OwnershipPolicy)
353         void Destroy()
354         {
355                 delete pointee_;
356         }
357
358         // Default value to initialize the pointer
359         static StoredType Default()
360         {
361                 return 0;
362         }
363
364 private:
365         /// Dereference operator is not implemented.
366         ReferenceType operator*();
367
368         // Data
369         StoredType pointee_;
370 };
371
372 template <class T>
373 inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp)
374 {
375         return sp.pointee_;
376 }
377
378 template <class T>
379 inline const typename LockedStorage<T>::StoredType &GetImplRef(const LockedStorage<T>& sp)
380 {
381         return sp.pointee_;
382 }
383
384 template <class T>
385 inline typename LockedStorage<T>::StoredType &GetImplRef(LockedStorage<T>& sp)
386 {
387         return sp.pointee_;
388 }
389
390
391 ////////////////////////////////////////////////////////////////////////////////
392 ///  \class ArrayStorage
393 ///
394 ///  \ingroup  SmartPointerStorageGroup
395 ///  Implementation of the ArrayStorage used by SmartPtr
396 ////////////////////////////////////////////////////////////////////////////////
397
398
399 template <class T>
400 class ArrayStorage
401 {
402 public:
403         typedef T *StoredType;    // the type of the pointee_ object
404         typedef T *InitPointerType; /// type used to declare OwnershipPolicy type.
405         typedef T *PointerType;   // type returned by operator->
406         typedef T &ReferenceType; // type returned by operator*
407
408         ArrayStorage() : pointee_(Default())
409         {}
410
411         // The storage policy doesn't initialize the stored pointer
412         //     which will be initialized by the OwnershipPolicy's Clone fn
413         ArrayStorage(const ArrayStorage &) : pointee_(0)
414         {}
415
416         template <class U>
417         ArrayStorage(const ArrayStorage<U>&) : pointee_(0)
418         {}
419
420         ArrayStorage(const StoredType &p) : pointee_(p) {}
421
422         PointerType operator->() const
423         {
424                 return pointee_;
425         }
426
427         ReferenceType operator*() const
428         {
429                 return *pointee_;
430         }
431
432         void Swap(ArrayStorage &rhs)
433         {
434                 std::swap(pointee_, rhs.pointee_);
435         }
436
437         // Accessors
438         template <class F>
439         friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp);
440
441         template <class F>
442         friend const typename ArrayStorage<F>::StoredType &GetImplRef(const ArrayStorage<F>& sp);
443
444         template <class F>
445         friend typename ArrayStorage<F>::StoredType &GetImplRef(ArrayStorage<F>& sp);
446
447 protected:
448         // Destroys the data stored
449         // (Destruction might be taken over by the OwnershipPolicy)
450         void Destroy()
451         {
452                 delete [] pointee_;
453         }
454
455         // Default value to initialize the pointer
456         static StoredType Default()
457         {
458                 return 0;
459         }
460
461 private:
462         // Data
463         StoredType pointee_;
464 };
465
466 template <class T>
467 inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp)
468 {
469         return sp.pointee_;
470 }
471
472 template <class T>
473 inline const typename ArrayStorage<T>::StoredType &GetImplRef(const ArrayStorage<T>& sp)
474 {
475         return sp.pointee_;
476 }
477
478 template <class T>
479 inline typename ArrayStorage<T>::StoredType &GetImplRef(ArrayStorage<T>& sp)
480 {
481         return sp.pointee_;
482 }
483
484
485 ////////////////////////////////////////////////////////////////////////////////
486 ///  \class RefCounted
487 ///
488 ///  \ingroup  SmartPointerOwnershipGroup
489 ///  Implementation of the OwnershipPolicy used by SmartPtr
490 ///  Provides a classic external reference counting implementation
491 ////////////////////////////////////////////////////////////////////////////////
492
493 template <class P>
494 class RefCounted
495 {
496 public:
497         RefCounted()
498                 : pCount_(static_cast<uintptr_t *>(
499                               SmallObject<>::operator new(sizeof(uintptr_t))))
500         {
501                 assert(pCount_!=0);
502                 *pCount_ = 1;
503         }
504
505         RefCounted(const RefCounted &rhs)
506                 : pCount_(rhs.pCount_)
507         {}
508
509         // MWCW lacks template friends, hence the following kludge
510         template <typename P1>
511         RefCounted(const RefCounted<P1>& rhs)
512                 : pCount_(reinterpret_cast<const RefCounted &>(rhs).pCount_)
513         {}
514
515         P Clone(const P &val)
516         {
517                 ++*pCount_;
518                 return val;
519         }
520
521         bool Release(const P &)
522         {
523                 if (!--*pCount_)
524                 {
525                         SmallObject<>::operator delete(pCount_, sizeof(uintptr_t));
526                         pCount_ = NULL;
527                         return true;
528                 }
529                 return false;
530         }
531
532         void Swap(RefCounted &rhs)
533         {
534                 std::swap(pCount_, rhs.pCount_);
535         }
536
537         enum { destructiveCopy = false };
538
539 private:
540         // Data
541         uintptr_t *pCount_;
542 };
543
544 ////////////////////////////////////////////////////////////////////////////////
545 ///  \struct RefCountedMT
546 ///
547 ///  \ingroup  SmartPointerOwnershipGroup
548 ///  Implementation of the OwnershipPolicy used by SmartPtr
549 ///  Implements external reference counting for multithreaded programs
550 ///  Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
551 ///
552 ///  \par Warning
553 ///  There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release"
554 ///  http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644
555 ///  As stated in bug 1408845, the Release function is not thread safe if a
556 ///  SmartPtr copy-constructor tries to copy the last pointer to an object in
557 ///  one thread, while the destructor is acting on the last pointer in another
558 ///  thread.  The existence of a race between a copy-constructor and destructor
559 ///  implies a design flaw at a higher level.  That race condition must be
560 ///  fixed at a higher design level, and no change to this class could fix it.
561 ////////////////////////////////////////////////////////////////////////////////
562
563 template <template <class, class> class ThreadingModel,
564          class MX = LOKI_DEFAULT_MUTEX >
565 struct RefCountedMTAdj
566 {
567         template <class P>
568         class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX >
569         {
570                 typedef ThreadingModel< RefCountedMT<P>, MX > base_type;
571                 typedef typename base_type::IntType       CountType;
572                 typedef volatile CountType               *CountPtrType;
573
574         public:
575                 RefCountedMT()
576                 {
577                         pCount_ = static_cast<CountPtrType>(
578                                       SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new(
579                                           sizeof(*pCount_)));
580                         assert(pCount_);
581                         //*pCount_ = 1;
582                         ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
583                 }
584
585                 RefCountedMT(const RefCountedMT &rhs)
586                         : pCount_(rhs.pCount_)
587                 {}
588
589                 //MWCW lacks template friends, hence the following kludge
590                 template <typename P1>
591                 RefCountedMT(const RefCountedMT<P1>& rhs)
592                         : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
593                 {}
594
595                 P Clone(const P &val)
596                 {
597                         ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_);
598                         return val;
599                 }
600
601                 bool Release(const P &)
602                 {
603                         bool isZero = false;
604                         ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero );
605                         if ( isZero )
606                         {
607                                 SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete(
608                                     const_cast<CountType *>(pCount_),
609                                     sizeof(*pCount_));
610                                 return true;
611                         }
612                         return false;
613                 }
614
615                 void Swap(RefCountedMT &rhs)
616                 {
617                         std::swap(pCount_, rhs.pCount_);
618                 }
619
620                 enum { destructiveCopy = false };
621
622         private:
623                 // Data
624                 CountPtrType pCount_;
625         };
626 };
627
628 ////////////////////////////////////////////////////////////////////////////////
629 ///  \class COMRefCounted
630 ///
631 ///  \ingroup  SmartPointerOwnershipGroup
632 ///  Implementation of the OwnershipPolicy used by SmartPtr
633 ///  Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
634 ////////////////////////////////////////////////////////////////////////////////
635
636 template <class P>
637 class COMRefCounted
638 {
639 public:
640         COMRefCounted()
641         {}
642
643         template <class U>
644         COMRefCounted(const COMRefCounted<U>&)
645         {}
646
647         static P Clone(const P &val)
648         {
649                 if(val!=0)
650                         val->AddRef();
651                 return val;
652         }
653
654         static bool Release(const P &val)
655         {
656                 if(val!=0)
657                         val->Release();
658                 return false;
659         }
660
661         enum { destructiveCopy = false };
662
663         static void Swap(COMRefCounted &)
664         {}
665 };
666
667 ////////////////////////////////////////////////////////////////////////////////
668 ///  \struct DeepCopy
669 ///
670 ///  \ingroup  SmartPointerOwnershipGroup
671 ///  Implementation of the OwnershipPolicy used by SmartPtr
672 ///  Implements deep copy semantics, assumes existence of a Clone() member
673 ///  function of the pointee type
674 ////////////////////////////////////////////////////////////////////////////////
675
676 template <class P>
677 struct DeepCopy
678 {
679         DeepCopy()
680         {}
681
682         template <class P1>
683         DeepCopy(const DeepCopy<P1>&)
684         {}
685
686         static P Clone(const P &val)
687         {
688                 return val->Clone();
689         }
690
691         static bool Release(const P &)
692         {
693                 return true;
694         }
695
696         static void Swap(DeepCopy &)
697         {}
698
699         enum { destructiveCopy = false };
700 };
701
702 ////////////////////////////////////////////////////////////////////////////////
703 ///  \class RefLinked
704 ///
705 ///  \ingroup  SmartPointerOwnershipGroup
706 ///  Implementation of the OwnershipPolicy used by SmartPtr
707 ///  Implements reference linking
708 ////////////////////////////////////////////////////////////////////////////////
709
710 namespace Private
711 {
712 class LOKI_EXPORT RefLinkedBase
713 {
714 public:
715         RefLinkedBase()
716         {
717                 prev_ = next_ = this;
718         }
719
720         RefLinkedBase(const RefLinkedBase &rhs);
721
722         bool Release();
723
724         void Swap(RefLinkedBase &rhs);
725
726         bool Merge( RefLinkedBase &rhs );
727
728         enum { destructiveCopy = false };
729
730 private:
731         static unsigned int CountPrevCycle( const RefLinkedBase *pThis );
732         static unsigned int CountNextCycle( const RefLinkedBase *pThis );
733         bool HasPrevNode( const RefLinkedBase *p ) const;
734         bool HasNextNode( const RefLinkedBase *p ) const;
735
736         mutable const RefLinkedBase *prev_;
737         mutable const RefLinkedBase *next_;
738 };
739 }
740
741 template <class P>
742 class RefLinked : public Private::RefLinkedBase
743 {
744 public:
745         RefLinked()
746         {}
747
748         template <class P1>
749         RefLinked(const RefLinked<P1>& rhs)
750                 : Private::RefLinkedBase(rhs)
751         {}
752
753         static P Clone(const P &val)
754         {
755                 return val;
756         }
757
758         bool Release(const P &)
759         {
760                 return Private::RefLinkedBase::Release();
761         }
762
763         template < class P1 >
764         bool Merge( RefLinked< P1 > & rhs )
765         {
766                 return Private::RefLinkedBase::Merge( rhs );
767         }
768 };
769
770 ////////////////////////////////////////////////////////////////////////////////
771 ///  \class DestructiveCopy
772 ///
773 ///  \ingroup  SmartPointerOwnershipGroup
774 ///  Implementation of the OwnershipPolicy used by SmartPtr
775 ///  Implements destructive copy semantics (a la std::auto_ptr)
776 ////////////////////////////////////////////////////////////////////////////////
777
778 template <class P>
779 class DestructiveCopy
780 {
781 public:
782         DestructiveCopy()
783         {}
784
785         template <class P1>
786         DestructiveCopy(const DestructiveCopy<P1>&)
787         {}
788
789         template <class P1>
790         static P Clone(P1 &val)
791         {
792                 P result(val);
793                 val = P1();
794                 return result;
795         }
796
797         static bool Release(const P &)
798         {
799                 return true;
800         }
801
802         static void Swap(DestructiveCopy &)
803         {}
804
805         enum { destructiveCopy = true };
806 };
807
808 ////////////////////////////////////////////////////////////////////////////////
809 ///  \class NoCopy
810 ///
811 ///  \ingroup  SmartPointerOwnershipGroup
812 ///  Implementation of the OwnershipPolicy used by SmartPtr
813 ///  Implements a policy that doesn't allow copying objects
814 ////////////////////////////////////////////////////////////////////////////////
815
816 template <class P>
817 class NoCopy
818 {
819 public:
820         NoCopy()
821         {}
822
823         template <class P1>
824         NoCopy(const NoCopy<P1>&)
825         {}
826
827         static P Clone(const P &)
828         {
829                 // Make it depended on template parameter
830                 static const bool DependedFalse = sizeof(P *) == 0;
831
832                 LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
833         }
834
835         static bool Release(const P &)
836         {
837                 return true;
838         }
839
840         static void Swap(NoCopy &)
841         {}
842
843         enum { destructiveCopy = false };
844 };
845
846 ////////////////////////////////////////////////////////////////////////////////
847 ///  \struct AllowConversion
848 ///
849 ///  \ingroup  SmartPointerConversionGroup
850 ///  Implementation of the ConversionPolicy used by SmartPtr
851 ///  Allows implicit conversion from SmartPtr to the pointee type
852 ////////////////////////////////////////////////////////////////////////////////
853
854 struct AllowConversion
855 {
856         enum { allow = true };
857
858         void Swap(AllowConversion &)
859         {}
860 };
861
862 ////////////////////////////////////////////////////////////////////////////////
863 ///  \struct DisallowConversion
864 ///
865 ///  \ingroup  SmartPointerConversionGroup
866 ///  Implementation of the ConversionPolicy used by SmartPtr
867 ///  Does not allow implicit conversion from SmartPtr to the pointee type
868 ///  You can initialize a DisallowConversion with an AllowConversion
869 ////////////////////////////////////////////////////////////////////////////////
870
871 struct DisallowConversion
872 {
873         DisallowConversion()
874         {}
875
876         DisallowConversion(const AllowConversion &)
877         {}
878
879         enum { allow = false };
880
881         void Swap(DisallowConversion &)
882         {}
883 };
884
885 ////////////////////////////////////////////////////////////////////////////////
886 ///  \struct NoCheck
887 ///
888 ///  \ingroup  SmartPointerCheckingGroup
889 ///  Implementation of the CheckingPolicy used by SmartPtr
890 ///  Well, it's clear what it does :o)
891 ////////////////////////////////////////////////////////////////////////////////
892
893 template <class P>
894 struct NoCheck
895 {
896         NoCheck()
897         {}
898
899         template <class P1>
900         NoCheck(const NoCheck<P1>&)
901         {}
902
903         static void OnDefault(const P &)
904         {}
905
906         static void OnInit(const P &)
907         {}
908
909         static void OnDereference(const P &)
910         {}
911
912         static void Swap(NoCheck &)
913         {}
914 };
915
916
917 ////////////////////////////////////////////////////////////////////////////////
918 ///  \struct AssertCheck
919 ///
920 ///  \ingroup  SmartPointerCheckingGroup
921 ///  Implementation of the CheckingPolicy used by SmartPtr
922 ///  Checks the pointer before dereference
923 ////////////////////////////////////////////////////////////////////////////////
924
925 template <class P>
926 struct AssertCheck
927 {
928         AssertCheck()
929         {}
930
931         template <class P1>
932         AssertCheck(const AssertCheck<P1>&)
933         {}
934
935         template <class P1>
936         AssertCheck(const NoCheck<P1>&)
937         {}
938
939         static void OnDefault(const P &)
940         {}
941
942         static void OnInit(const P &)
943         {}
944
945         static void OnDereference(P val)
946         {
947                 assert(val);
948                 (void)val;
949         }
950
951         static void Swap(AssertCheck &)
952         {}
953 };
954
955 ////////////////////////////////////////////////////////////////////////////////
956 ///  \struct AssertCheckStrict
957 ///
958 ///  \ingroup  SmartPointerCheckingGroup
959 ///  Implementation of the CheckingPolicy used by SmartPtr
960 ///  Checks the pointer against zero upon initialization and before dereference
961 ///  You can initialize an AssertCheckStrict with an AssertCheck
962 ////////////////////////////////////////////////////////////////////////////////
963
964 template <class P>
965 struct AssertCheckStrict
966 {
967         AssertCheckStrict()
968         {}
969
970         template <class U>
971         AssertCheckStrict(const AssertCheckStrict<U>&)
972         {}
973
974         template <class U>
975         AssertCheckStrict(const AssertCheck<U>&)
976         {}
977
978         template <class P1>
979         AssertCheckStrict(const NoCheck<P1>&)
980         {}
981
982         static void OnDefault(P val)
983         {
984                 assert(val);
985         }
986
987         static void OnInit(P val)
988         {
989                 assert(val);
990         }
991
992         static void OnDereference(P val)
993         {
994                 assert(val);
995         }
996
997         static void Swap(AssertCheckStrict &)
998         {}
999 };
1000
1001 ////////////////////////////////////////////////////////////////////////////////
1002 ///  \struct NullPointerException
1003 ///
1004 ///  \ingroup SmartPointerGroup
1005 ///  Used by some implementations of the CheckingPolicy used by SmartPtr
1006 ////////////////////////////////////////////////////////////////////////////////
1007
1008 struct NullPointerException : public std::runtime_error
1009 {
1010         NullPointerException() : std::runtime_error(std::string(""))
1011         { }
1012         const char *what() const throw()
1013         {
1014                 return "Null Pointer Exception";
1015         }
1016 };
1017
1018 ////////////////////////////////////////////////////////////////////////////////
1019 ///  \struct RejectNullStatic
1020 ///
1021 ///  \ingroup  SmartPointerCheckingGroup
1022 ///  Implementation of the CheckingPolicy used by SmartPtr
1023 ///  Checks the pointer upon initialization and before dereference
1024 ////////////////////////////////////////////////////////////////////////////////
1025
1026 template <class P>
1027 struct RejectNullStatic
1028 {
1029         RejectNullStatic()
1030         {}
1031
1032         template <class P1>
1033         RejectNullStatic(const RejectNullStatic<P1>&)
1034         {}
1035
1036         template <class P1>
1037         RejectNullStatic(const NoCheck<P1>&)
1038         {}
1039
1040         template <class P1>
1041         RejectNullStatic(const AssertCheck<P1>&)
1042         {}
1043
1044         template <class P1>
1045         RejectNullStatic(const AssertCheckStrict<P1>&)
1046         {}
1047
1048         static void OnDefault(const P &)
1049         {
1050                 // Make it depended on template parameter
1051                 static const bool DependedFalse = sizeof(P *) == 0;
1052
1053                 LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
1054         }
1055
1056         static void OnInit(const P &val)
1057         {
1058                 if (!val) throw NullPointerException();
1059         }
1060
1061         static void OnDereference(const P &val)
1062         {
1063                 if (!val) throw NullPointerException();
1064         }
1065
1066         static void Swap(RejectNullStatic &)
1067         {}
1068 };
1069
1070 ////////////////////////////////////////////////////////////////////////////////
1071 ///  \struct RejectNull
1072 ///
1073 ///  \ingroup  SmartPointerCheckingGroup
1074 ///  Implementation of the CheckingPolicy used by SmartPtr
1075 ///  Checks the pointer before dereference
1076 ////////////////////////////////////////////////////////////////////////////////
1077
1078 template <class P>
1079 struct RejectNull
1080 {
1081         RejectNull()
1082         {}
1083
1084         template <class P1>
1085         RejectNull(const RejectNull<P1>&)
1086         {}
1087
1088         static void OnInit(P)
1089         {}
1090
1091         static void OnDefault(P)
1092         {}
1093
1094         void OnDereference(P val)
1095         {
1096                 if (!val) throw NullPointerException();
1097         }
1098
1099         void OnDereference(P val) const
1100         {
1101                 if (!val) throw NullPointerException();
1102         }
1103
1104         void Swap(RejectNull &)
1105         {}
1106 };
1107
1108 ////////////////////////////////////////////////////////////////////////////////
1109 ///  \struct RejectNullStrict
1110 ///
1111 ///  \ingroup  SmartPointerCheckingGroup
1112 ///  Implementation of the CheckingPolicy used by SmartPtr
1113 ///  Checks the pointer upon initialization and before dereference
1114 ////////////////////////////////////////////////////////////////////////////////
1115
1116 template <class P>
1117 struct RejectNullStrict
1118 {
1119         RejectNullStrict()
1120         {}
1121
1122         template <class P1>
1123         RejectNullStrict(const RejectNullStrict<P1>&)
1124         {}
1125
1126         template <class P1>
1127         RejectNullStrict(const RejectNull<P1>&)
1128         {}
1129
1130         static void OnInit(P val)
1131         {
1132                 if (!val) throw NullPointerException();
1133         }
1134
1135         void OnDereference(P val)
1136         {
1137                 OnInit(val);
1138         }
1139
1140         void OnDereference(P val) const
1141         {
1142                 OnInit(val);
1143         }
1144
1145         void Swap(RejectNullStrict &)
1146         {}
1147 };
1148
1149
1150 ////////////////////////////////////////////////////////////////////////////////
1151 // class template SmartPtr (declaration)
1152 // The reason for all the fuss above
1153 ////////////////////////////////////////////////////////////////////////////////
1154
1155 template
1156 <
1157 typename T,
1158          template <class> class OwnershipPolicy = RefCounted,
1159          class ConversionPolicy = DisallowConversion,
1160          template <class> class CheckingPolicy = AssertCheck,
1161          template <class> class StoragePolicy = DefaultSPStorage,
1162          template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
1163          >
1164 class SmartPtr;
1165
1166 ////////////////////////////////////////////////////////////////////////////////
1167 // class template SmartPtrDef (definition)
1168 // this class added to unify the usage of SmartPtr
1169 // instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
1170 ////////////////////////////////////////////////////////////////////////////////
1171
1172 template
1173 <
1174 typename T,
1175          template <class> class OwnershipPolicy = RefCounted,
1176          class ConversionPolicy = DisallowConversion,
1177          template <class> class CheckingPolicy = AssertCheck,
1178          template <class> class StoragePolicy = DefaultSPStorage,
1179          template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
1180          >
1181 struct SmartPtrDef
1182 {
1183         typedef SmartPtr
1184         <
1185         T,
1186         OwnershipPolicy,
1187         ConversionPolicy,
1188         CheckingPolicy,
1189         StoragePolicy,
1190         ConstnessPolicy
1191         >
1192         type;
1193 };
1194
1195 ////////////////////////////////////////////////////////////////////////////////
1196 ///  \class SmartPtr
1197 ///
1198 ///  \ingroup SmartPointerGroup
1199 ///
1200 ///  \param OwnershipPolicy  default =  RefCounted,
1201 ///  \param ConversionPolicy default = DisallowConversion,
1202 ///  \param CheckingPolicy default = AssertCheck,
1203 ///  \param StoragePolicy default = DefaultSPStorage
1204 ///  \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
1205 ///
1206 ///  \par IMPORTANT NOTE
1207 ///  Due to threading issues, the OwnershipPolicy has been changed as follows:
1208 ///
1209 ///     - Release() returns a boolean saying if that was the last release
1210 ///        so the pointer can be deleted by the StoragePolicy
1211 ///     - IsUnique() was removed
1212 ////////////////////////////////////////////////////////////////////////////////
1213
1214 template
1215 <
1216 typename T,
1217          template <class> class OwnershipPolicy,
1218          class ConversionPolicy,
1219          template <class> class CheckingPolicy,
1220          template <class> class StoragePolicy,
1221          template <class> class ConstnessPolicy
1222          >
1223 class SmartPtr
1224         : public StoragePolicy<T>
1225         , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
1226         , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
1227         , public ConversionPolicy
1228 {
1229         typedef StoragePolicy<T> SP;
1230         typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
1231         typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
1232         typedef ConversionPolicy CP;
1233
1234 public:
1235         typedef typename ConstnessPolicy<T>::Type *ConstPointerType;
1236         typedef typename ConstnessPolicy<T>::Type &ConstReferenceType;
1237
1238         typedef typename SP::PointerType PointerType;
1239         typedef typename SP::StoredType StoredType;
1240         typedef typename SP::ReferenceType ReferenceType;
1241
1242         typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
1243         CopyArg;
1244
1245 private:
1246         struct NeverMatched {};
1247
1248 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
1249         typedef typename Select< CP::allow, const StoredType &, NeverMatched>::Result ImplicitArg;
1250         typedef typename Select<!CP::allow, const StoredType &, NeverMatched>::Result ExplicitArg;
1251 #else
1252         typedef const StoredType &ImplicitArg;
1253         typedef typename Select<false, const StoredType &, NeverMatched>::Result ExplicitArg;
1254 #endif
1255
1256 public:
1257
1258         SmartPtr()
1259         {
1260                 KP::OnDefault(GetImpl(*this));
1261         }
1262
1263         explicit
1264         SmartPtr(ExplicitArg p) : SP(p)
1265         {
1266                 KP::OnInit(GetImpl(*this));
1267         }
1268
1269         SmartPtr(ImplicitArg p) : SP(p)
1270         {
1271                 KP::OnInit(GetImpl(*this));
1272         }
1273
1274         SmartPtr(CopyArg &rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1275         {
1276                 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
1277         }
1278
1279         template
1280         <
1281         typename T1,
1282                  template <class> class OP1,
1283                  class CP1,
1284                  template <class> class KP1,
1285                  template <class> class SP1,
1286                  template <class> class CNP1
1287                  >
1288         SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1289                 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1290         {
1291                 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
1292         }
1293
1294         template
1295         <
1296         typename T1,
1297                  template <class> class OP1,
1298                  class CP1,
1299                  template <class> class KP1,
1300                  template <class> class SP1,
1301                  template <class> class CNP1
1302                  >
1303         SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1304                 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1305         {
1306                 GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
1307         }
1308
1309         SmartPtr(RefToValue<SmartPtr> rhs)
1310                 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
1311         {}
1312
1313         operator RefToValue<SmartPtr>()
1314         {
1315                 return RefToValue<SmartPtr>(*this);
1316         }
1317
1318         SmartPtr &operator=(CopyArg &rhs)
1319         {
1320                 SmartPtr temp(rhs);
1321                 temp.Swap(*this);
1322                 return *this;
1323         }
1324
1325         template
1326         <
1327         typename T1,
1328                  template <class> class OP1,
1329                  class CP1,
1330                  template <class> class KP1,
1331                  template <class> class SP1,
1332                  template <class> class CNP1
1333                  >
1334         SmartPtr &operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1335         {
1336                 SmartPtr temp(rhs);
1337                 temp.Swap(*this);
1338                 return *this;
1339         }
1340
1341         template
1342         <
1343         typename T1,
1344                  template <class> class OP1,
1345                  class CP1,
1346                  template <class> class KP1,
1347                  template <class> class SP1,
1348                  template <class> class CNP1
1349                  >
1350         SmartPtr &operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
1351         {
1352                 SmartPtr temp(rhs);
1353                 temp.Swap(*this);
1354                 return *this;
1355         }
1356
1357         void Swap(SmartPtr &rhs)
1358         {
1359                 OP::Swap(rhs);
1360                 CP::Swap(rhs);
1361                 KP::Swap(rhs);
1362                 SP::Swap(rhs);
1363         }
1364
1365         ~SmartPtr()
1366         {
1367                 if (OP::Release(GetImpl(*static_cast<SP *>(this))))
1368                 {
1369                         SP::Destroy();
1370                 }
1371         }
1372
1373 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1374
1375         // old non standard in class definition of friends
1376         friend inline void Release(SmartPtr &sp, typename SP::StoredType &p)
1377         {
1378                 p = GetImplRef(sp);
1379                 GetImplRef(sp) = SP::Default();
1380         }
1381
1382         friend inline void Reset(SmartPtr &sp, typename SP::StoredType p)
1383         {
1384                 SmartPtr(p).Swap(sp);
1385         }
1386
1387 #else
1388
1389         template
1390         <
1391         typename T1,
1392                  template <class> class OP1,
1393                  class CP1,
1394                  template <class> class KP1,
1395                  template <class> class SP1,
1396                  template <class> class CNP1
1397                  >
1398         friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
1399                             typename SP1<T1>::StoredType &p);
1400
1401         template
1402         <
1403         typename T1,
1404                  template <class> class OP1,
1405                  class CP1,
1406                  template <class> class KP1,
1407                  template <class> class SP1,
1408                  template <class> class CNP1
1409                  >
1410         friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
1411                           typename SP1<T1>::StoredType p);
1412 #endif
1413
1414
1415         template
1416         <
1417         typename T1,
1418                  template <class> class OP1,
1419                  class CP1,
1420                  template <class> class KP1,
1421                  template <class> class SP1,
1422                  template <class> class CNP1
1423                  >
1424         bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1425         {
1426                 if ( GetImpl( *this ) != GetImpl( rhs ) )
1427                 {
1428                         return false;
1429                 }
1430                 return OP::template Merge( rhs );
1431         }
1432
1433         PointerType operator->()
1434         {
1435                 KP::OnDereference(GetImplRef(*this));
1436                 return SP::operator->();
1437         }
1438
1439         ConstPointerType operator->() const
1440         {
1441                 KP::OnDereference(GetImplRef(*this));
1442                 return SP::operator->();
1443         }
1444
1445         ReferenceType operator*()
1446         {
1447                 KP::OnDereference(GetImplRef(*this));
1448                 return SP::operator*();
1449         }
1450
1451         ConstReferenceType operator*() const
1452         {
1453                 KP::OnDereference(GetImplRef(*this));
1454                 return SP::operator*();
1455         }
1456
1457         bool operator!() const // Enables "if (!sp) ..."
1458         {
1459                 return GetImpl(*this) == 0;
1460         }
1461
1462         static inline T *GetPointer( const SmartPtr &sp )
1463         {
1464                 return GetImpl( sp );
1465         }
1466
1467         // Ambiguity buster
1468         template
1469         <
1470         typename T1,
1471                  template <class> class OP1,
1472                  class CP1,
1473                  template <class> class KP1,
1474                  template <class> class SP1,
1475                  template <class> class CNP1
1476                  >
1477         bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
1478         {
1479                 return GetImpl(*this) == GetImpl(rhs);
1480         }
1481
1482         // Ambiguity buster
1483         template
1484         <
1485         typename T1,
1486                  template <class> class OP1,
1487                  class CP1,
1488                  template <class> class KP1,
1489                  template <class> class SP1,
1490                  template <class> class CNP1
1491                  >
1492         bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
1493         {
1494                 return !(*this == rhs);
1495         }
1496
1497         // Ambiguity buster
1498         template
1499         <
1500         typename T1,
1501                  template <class> class OP1,
1502                  class CP1,
1503                  template <class> class KP1,
1504                  template <class> class SP1,
1505                  template <class> class CNP1
1506                  >
1507         bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
1508         {
1509                 return GetImpl(*this) < GetImpl(rhs);
1510         }
1511
1512         // Ambiguity buster
1513         template
1514         <
1515         typename T1,
1516                  template <class> class OP1,
1517                  class CP1,
1518                  template <class> class KP1,
1519                  template <class> class SP1,
1520                  template <class> class CNP1
1521                  >
1522         inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1523         {
1524                 return ( GetImpl( rhs ) < GetImpl( *this ) );
1525         }
1526
1527         // Ambiguity buster
1528         template
1529         <
1530         typename T1,
1531                  template <class> class OP1,
1532                  class CP1,
1533                  template <class> class KP1,
1534                  template <class> class SP1,
1535                  template <class> class CNP1
1536                  >
1537         inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1538         {
1539                 return !( GetImpl( rhs ) < GetImpl( *this ) );
1540         }
1541
1542         // Ambiguity buster
1543         template
1544         <
1545         typename T1,
1546                  template <class> class OP1,
1547                  class CP1,
1548                  template <class> class KP1,
1549                  template <class> class SP1,
1550                  template <class> class CNP1
1551                  >
1552         inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
1553         {
1554                 return !( GetImpl( *this ) < GetImpl( rhs ) );
1555         }
1556
1557 private:
1558         // Helper for enabling 'if (sp)'
1559         struct Tester
1560         {
1561                 Tester(int) {}
1562                 void dummy() {}
1563         };
1564
1565         typedef void (Tester::*unspecified_boolean_type_)();
1566
1567         typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
1568         unspecified_boolean_type;
1569
1570 public:
1571         // enable 'if (sp)'
1572         operator unspecified_boolean_type() const
1573         {
1574                 return !*this ? 0 : &Tester::dummy;
1575         }
1576
1577 private:
1578         // Helper for disallowing automatic conversion
1579         struct Insipid
1580         {
1581                 Insipid(PointerType) {}
1582         };
1583
1584         typedef typename Select<CP::allow, PointerType, Insipid>::Result
1585         AutomaticConversionResult;
1586
1587 public:
1588         operator AutomaticConversionResult() const
1589         {
1590                 return GetImpl(*this);
1591         }
1592 };
1593
1594
1595 ////////////////////////////////////////////////////////////////////////////////
1596 // friends
1597 ////////////////////////////////////////////////////////////////////////////////
1598
1599 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1600
1601 template
1602 <
1603 typename T,
1604          template <class> class OP,
1605          class CP,
1606          template <class> class KP,
1607          template <class> class SP,
1608          template <class> class CNP
1609          >
1610 inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
1611                     typename SP<T>::StoredType &p)
1612 {
1613         p = GetImplRef(sp);
1614         GetImplRef(sp) = SP<T>::Default();
1615 }
1616
1617 template
1618 <
1619 typename T,
1620          template <class> class OP,
1621          class CP,
1622          template <class> class KP,
1623          template <class> class SP,
1624          template <class> class CNP
1625          >
1626 inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
1627                   typename SP<T>::StoredType p)
1628 {
1629         SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp);
1630 }
1631
1632 #endif
1633
1634 ////////////////////////////////////////////////////////////////////////////////
1635 // free comparison operators for class template SmartPtr
1636 ////////////////////////////////////////////////////////////////////////////////
1637
1638 ////////////////////////////////////////////////////////////////////////////////
1639 ///  operator== for lhs = SmartPtr, rhs = raw pointer
1640 ///  \ingroup SmartPointerGroup
1641 ////////////////////////////////////////////////////////////////////////////////
1642
1643 template
1644 <
1645 typename T,
1646          template <class> class OP,
1647          class CP,
1648          template <class> class KP,
1649          template <class> class SP,
1650          template <class> class CNP1,
1651          typename U
1652          >
1653 inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs,
1654                        U *rhs)
1655 {
1656         return GetImpl(lhs) == rhs;
1657 }
1658
1659 ////////////////////////////////////////////////////////////////////////////////
1660 ///  operator== for lhs = raw pointer, rhs = SmartPtr
1661 ///  \ingroup SmartPointerGroup
1662 ////////////////////////////////////////////////////////////////////////////////
1663
1664 template
1665 <
1666 typename T,
1667          template <class> class OP,
1668          class CP,
1669          template <class> class KP,
1670          template <class> class SP,
1671          template <class> class CNP1,
1672          typename U
1673          >
1674 inline bool operator==(U *lhs,
1675                        const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs)
1676 {
1677         return rhs == lhs;
1678 }
1679
1680 ////////////////////////////////////////////////////////////////////////////////
1681 ///  operator!= for lhs = SmartPtr, rhs = raw pointer
1682 ///  \ingroup SmartPointerGroup
1683 ////////////////////////////////////////////////////////////////////////////////
1684
1685 template
1686 <
1687 typename T,
1688          template <class> class OP,
1689          class CP,
1690          template <class> class KP,
1691          template <class> class SP,
1692          template <class> class CNP,
1693          typename U
1694          >
1695 inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1696                        U *rhs)
1697 {
1698         return !(lhs == rhs);
1699 }
1700
1701 ////////////////////////////////////////////////////////////////////////////////
1702 ///  operator!= for lhs = raw pointer, rhs = SmartPtr
1703 ///  \ingroup SmartPointerGroup
1704 ////////////////////////////////////////////////////////////////////////////////
1705
1706 template
1707 <
1708 typename T,
1709          template <class> class OP,
1710          class CP,
1711          template <class> class KP,
1712          template <class> class SP,
1713          template <class> class CNP,
1714          typename U
1715          >
1716 inline bool operator!=(U *lhs,
1717                        const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1718 {
1719         return rhs != lhs;
1720 }
1721
1722 ////////////////////////////////////////////////////////////////////////////////
1723 ///  operator< for lhs = SmartPtr, rhs = raw pointer
1724 ///  \ingroup SmartPointerGroup
1725 ////////////////////////////////////////////////////////////////////////////////
1726
1727 template
1728 <
1729 typename T,
1730          template <class> class OP,
1731          class CP,
1732          template <class> class KP,
1733          template <class> class SP,
1734          template <class> class CNP,
1735          typename U
1736          >
1737 inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1738                       U *rhs)
1739 {
1740         return ( GetImpl( lhs ) < rhs );
1741 }
1742
1743 ////////////////////////////////////////////////////////////////////////////////
1744 ///  operator< for lhs = raw pointer, rhs = SmartPtr
1745 ///  \ingroup SmartPointerGroup
1746 ////////////////////////////////////////////////////////////////////////////////
1747
1748 template
1749 <
1750 typename T,
1751          template <class> class OP,
1752          class CP,
1753          template <class> class KP,
1754          template <class> class SP,
1755          template <class> class CNP,
1756          typename U
1757          >
1758 inline bool operator<(U *lhs,
1759                       const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1760 {
1761         return ( GetImpl( rhs ) < lhs );
1762 }
1763
1764 ////////////////////////////////////////////////////////////////////////////////
1765 //  operator> for lhs = SmartPtr, rhs = raw pointer
1766 ///  \ingroup SmartPointerGroup
1767 ////////////////////////////////////////////////////////////////////////////////
1768
1769 template
1770 <
1771 typename T,
1772          template <class> class OP,
1773          class CP,
1774          template <class> class KP,
1775          template <class> class SP,
1776          template <class> class CNP,
1777          typename U
1778          >
1779 inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1780                       U *rhs)
1781 {
1782         return rhs < lhs;
1783 }
1784
1785 ////////////////////////////////////////////////////////////////////////////////
1786 ///  operator> for lhs = raw pointer, rhs = SmartPtr
1787 ///  \ingroup SmartPointerGroup
1788 ////////////////////////////////////////////////////////////////////////////////
1789
1790 template
1791 <
1792 typename T,
1793          template <class> class OP,
1794          class CP,
1795          template <class> class KP,
1796          template <class> class SP,
1797          template <class> class CNP,
1798          typename U
1799          >
1800 inline bool operator>(U *lhs,
1801                       const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1802 {
1803         return rhs < lhs;
1804 }
1805
1806 ////////////////////////////////////////////////////////////////////////////////
1807 ///  operator<= for lhs = SmartPtr, rhs = raw pointer
1808 ///  \ingroup SmartPointerGroup
1809 ////////////////////////////////////////////////////////////////////////////////
1810
1811 template
1812 <
1813 typename T,
1814          template <class> class OP,
1815          class CP,
1816          template <class> class KP,
1817          template <class> class SP,
1818          template <class> class CNP,
1819          typename U
1820          >
1821 inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1822                        U *rhs)
1823 {
1824         return !(rhs < lhs);
1825 }
1826
1827 ////////////////////////////////////////////////////////////////////////////////
1828 ///  operator<= for lhs = raw pointer, rhs = SmartPtr
1829 ///  \ingroup SmartPointerGroup
1830 ////////////////////////////////////////////////////////////////////////////////
1831
1832 template
1833 <
1834 typename T,
1835          template <class> class OP,
1836          class CP,
1837          template <class> class KP,
1838          template <class> class SP,
1839          template <class> class CNP,
1840          typename U
1841          >
1842 inline bool operator<=(U *lhs,
1843                        const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1844 {
1845         return !(rhs < lhs);
1846 }
1847
1848 ////////////////////////////////////////////////////////////////////////////////
1849 ///  operator>= for lhs = SmartPtr, rhs = raw pointer
1850 ///  \ingroup SmartPointerGroup
1851 ////////////////////////////////////////////////////////////////////////////////
1852
1853 template
1854 <
1855 typename T,
1856          template <class> class OP,
1857          class CP,
1858          template <class> class KP,
1859          template <class> class SP,
1860          template <class> class CNP,
1861          typename U
1862          >
1863 inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1864                        U *rhs)
1865 {
1866         return !(lhs < rhs);
1867 }
1868
1869 ////////////////////////////////////////////////////////////////////////////////
1870 ///  operator>= for lhs = raw pointer, rhs = SmartPtr
1871 ///  \ingroup SmartPointerGroup
1872 ////////////////////////////////////////////////////////////////////////////////
1873
1874 template
1875 <
1876 typename T,
1877          template <class> class OP,
1878          class CP,
1879          template <class> class KP,
1880          template <class> class SP,
1881          template <class> class CNP,
1882          typename U
1883          >
1884 inline bool operator>=(U *lhs,
1885                        const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
1886 {
1887         return !(lhs < rhs);
1888 }
1889
1890 } // namespace Loki
1891
1892 ////////////////////////////////////////////////////////////////////////////////
1893 ///  specialization of std::less for SmartPtr
1894 ///  \ingroup SmartPointerGroup
1895 ////////////////////////////////////////////////////////////////////////////////
1896
1897 namespace std
1898 {
1899 template
1900 <
1901 typename T,
1902          template <class> class OP,
1903          class CP,
1904          template <class> class KP,
1905          template <class> class SP,
1906          template <class> class CNP
1907          >
1908 struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > >
1909                 : public binary_function<Loki::SmartPtr<T, OP, CP, KP, SP, CNP >,
1910                   Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool>
1911 {
1912         bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
1913                         const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const
1914         {
1915                 return less<T *>()(GetImpl(lhs), GetImpl(rhs));
1916         }
1917 };
1918 }
1919
1920 #endif // end file guardian
1921