]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/StrongPtr.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / StrongPtr.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2006 Rich Sposato
4 // The copyright on this file is protected under the terms of the MIT license.
5 //
6 // Permission to use, copy, modify, distribute and sell this software for any
7 //     purpose is hereby granted without fee, provided that the above copyright
8 //     notice appear in all copies and that both that copyright notice and this
9 //     permission notice appear in supporting documentation.
10 // The author makes no representations about the
11 //     suitability of this software for any purpose. It is provided "as is"
12 //     without express or implied warranty.
13 ////////////////////////////////////////////////////////////////////////////////
14 #ifndef LOKI_STRONG_PTR_INC_
15 #define LOKI_STRONG_PTR_INC_
16
17 // $Id: StrongPtr.h 914 2008-12-19 00:39:29Z rich_sposato $
18
19
20 #include <loki/SmartPtr.h>
21 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
22 #include <loki/Threads.h>
23 #endif
24
25
26 ////////////////////////////////////////////////////////////////////////////////
27 ///
28 ///  \par Terminology
29 ///   These terms are used within this file's comments.
30 ///   -# StrongPtr : Class used to implement both strong and weak pointers. The
31 ///      second template parameter determines if a StrongPtr is weak or strong.
32 ///   -# Strong pointer : A pointer that claims ownership of a shared object.
33 ///      When the last strong copointer dies, the object is destroyed even if
34 ///      there are weak copointers.
35 ///   -# Weak pointer : A pointer that does not own the shared object it points
36 ///       to.  It only destroys the shared object if there no strong copointers
37 ///       exist when it dies.
38 ///   -# Copointers : All the pointers that refer to the same shared object.
39 ///      The copointers must have the same ownership policy, but the other
40 ///      policies may be different.
41 ///   -# Pointee : The shared object.
42 ///
43 ///  \par OwnershipPolicy
44 ///   The ownership policy has the pointer to the actual object, and it also
45 ///   keeps track of the strong and weak copointers so that it can know if any
46 ///   strong copointers remain.  The plain pointer it maintains is stored as a
47 ///   void pointer, which allows the ownership policy classes to be monolithic
48 ///   classes instead of template classes.  As monolithic classes, they reduce
49 ///   amount of code-bloat.
50 ///
51 ///  \par Writing Your Own OwnershipPolicy
52 ///   If you write your own policy, you must implement these 12 functions:
53 ///   -# explicit YourPolicy( bool strong )
54 ///   -# YourPolicy( void * p, bool strong )
55 ///   -# YourPolicy( const YourPolicy & rhs, bool strong )
56 ///   -# bool Release( bool strong )
57 ///   -# void Increment( bool strong )
58 ///   -# bool Decrement( bool strong )
59 ///   -# bool HasStrongPointer( void ) const
60 ///   -# void Swap( YourPolicy & rhs )
61 ///   -# void SetPointer( void * p )
62 ///   -# void ZapPointer( void )
63 ///   -# void * GetPointer( void ) const
64 ///   -# void * & GetPointerRef( void ) const
65 ///   It is strongly recommended that all 12 of these functions be protected
66 ///   instead of public.  These two functions are optional for single-threaded
67 ///   policies, but required for multi-threaded policies:
68 ///   -# void Lock( void ) const
69 ///   -# void Unlock( void ) const
70 ///   This function is entirely optional:
71 ///   -# bool Merge( TwoRefLinks & rhs )
72 ///
73 ///  \par DeletePolicy
74 ///   The delete policy provides a mechanism to destroy an object and a default
75 ///   value for an uninitialized pointer.  You can override this policy with
76 ///   your own when using the Singleton, NullObject, or Prototype design
77 ///   patterns.
78 ///
79 ///  \par Writing Your Own DeletePolicy
80 ///   If you write your own policy, you must implement these 3 functions:
81 ///   -# void static Delete( const P * p )
82 ///   -# static P * Default( void )
83 ///   -# void Swap( YourResetPolicy & )
84 ///
85 ///  \par ResetPolicy
86 ///   A reset policy tells the ReleaseAll and ResetAll functions whether they
87 ///   should release or reset the StrongPtr copointers.  These functions do
88 ///   not affect just one StrongPtr, but all copointers.  That is unlike
89 ///   SmartPtr where the Release and Reset functions only affect 1 SmartPtr,
90 ///   and leave all copointers untouched.  A useful trick you can do with the
91 ///   ResetPolicy is to not allow reset when a strong pointer exists, and then
92 ///   use the NoCheck policy for all strong pointers.  The reset policy
93 ///   guarantees the strong pointers always have a valid pointee, so checking
94 ///   is not required; but weak pointers may still require checking.
95 ///
96 ///  \par Writing Your Own ResetPolicy
97 ///   If you write your own policy, you must implement these 2 functions:
98 ///   -# bool OnReleaseAll( bool ) const
99 ///   -# bool OnResetAll( bool ) const
100 ///   The bool parameter means that this was called with a strong pointer or
101 ///   one of its copointers is strong.  The return value means the pointer
102 ///   can be reset or released.
103 ///
104 ///  \defgroup  StrongPointerOwnershipGroup StrongPtr Ownership policies
105 ///  \ingroup   SmartPointerGroup
106 ///  \defgroup  StrongPointerDeleteGroup Delete policies
107 ///  \ingroup   SmartPointerGroup
108 ///  \defgroup  StrongPointerResetGroup Reset policies
109 ///  \ingroup   SmartPointerGroup
110 ////////////////////////////////////////////////////////////////////////////////
111
112
113 namespace Loki
114 {
115
116
117 ////////////////////////////////////////////////////////////////////////////////
118 ///  \class DeleteUsingFree
119 ///
120 ///  \ingroup  StrongPointerDeleteGroup
121 ///  Implementation of the DeletePolicy used by StrongPtr.  Uses explicit call
122 ///   to T's destructor followed by call to free.  This policy is useful for
123 ///   managing the lifetime of pointers to structs returned by C functions.
124 ////////////////////////////////////////////////////////////////////////////////
125
126 template < class P >
127 class DeleteUsingFree
128 {
129 public:
130         inline void static Delete( const P *p )
131         {
132                 if ( 0 != p )
133                 {
134                         p->~P();
135                         ::free( p );
136                 }
137         }
138
139         /// Provides default value to initialize the pointer
140         inline static P *Default( void )
141         {
142                 return 0;
143         }
144
145         inline void Swap( DeleteUsingFree & ) {}
146 };
147
148 ////////////////////////////////////////////////////////////////////////////////
149 ///  \class DeleteNothing
150 ///
151 ///  \ingroup  StrongPointerDeleteGroup
152 ///  Implementation of the DeletePolicy used by StrongPtr.  This will never
153 ///   delete anything.  You can use this policy with pointers to an undefined
154 ///   type or a pure interface class with a protected destructor.
155 ////////////////////////////////////////////////////////////////////////////////
156
157 template < class P >
158 class DeleteNothing
159 {
160 public:
161         inline static void Delete( const P * )
162         {
163                 // Do nothing at all!
164         }
165
166         inline static P *Default( void )
167         {
168                 return 0;
169         }
170
171         inline void Swap( DeleteNothing & ) {}
172 };
173
174 ////////////////////////////////////////////////////////////////////////////////
175 ///  \class DeleteSingle
176 ///
177 ///  \ingroup  StrongPointerDeleteGroup
178 ///  Implementation of the DeletePolicy used by StrongPtr.  This deletes just
179 ///   one shared object.  This is the default class for the DeletePolicy.
180 ////////////////////////////////////////////////////////////////////////////////
181
182 template < class P >
183 class DeleteSingle
184 {
185 public:
186         inline static void Delete( const P *p )
187         {
188                 /** @note If you see an error message about a negative subscript, that
189                  means your are attempting to use Loki to delete an incomplete type.
190                  Please don't use this policy with incomplete types; you may want to
191                  use DeleteNothing instead.
192                  */
193                 typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
194                 delete p;
195         }
196
197         inline static P *Default( void )
198         {
199                 return 0;
200         }
201
202         inline void Swap( DeleteSingle & ) {}
203 };
204
205 ////////////////////////////////////////////////////////////////////////////////
206 ///  \class DeleteArray
207 ///
208 ///  \ingroup  StrongPointerDeleteGroup
209 ///  Implementation of the DeletePolicy used by StrongPtr.  This deletes an
210 ///   array of shared objects.
211 ////////////////////////////////////////////////////////////////////////////////
212
213 template < class P >
214 class DeleteArray
215 {
216 public:
217         inline static void Delete( const P *p )
218         {
219                 /** @note If you see an error message about a negative subscript, that
220                  means your are attempting to use Loki to delete an incomplete type.
221                  Please don't use this policy with incomplete types; you may want to
222                  use DeleteNothing instead.
223                  */
224                 typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
225                 delete [] p;
226         }
227
228         inline static P *Default( void )
229         {
230                 return 0;
231         }
232
233         inline void Swap( DeleteArray & ) {}
234 };
235
236 ////////////////////////////////////////////////////////////////////////////////
237 ///  \class CantResetWithStrong
238 ///
239 ///  \ingroup  StrongPointerResetGroup
240 ///  Implementation of the ResetPolicy used by StrongPtr.  This is the default
241 ///   ResetPolicy for StrongPtr.  It forbids reset and release only if a strong
242 ///   copointer exists.
243 ////////////////////////////////////////////////////////////////////////////////
244
245 template < class P >
246 struct CantResetWithStrong
247 {
248         inline bool OnReleaseAll( bool hasStrongPtr ) const
249         {
250                 return ! hasStrongPtr;
251         }
252
253         inline bool OnResetAll( bool hasStrongPtr ) const
254         {
255                 return ! hasStrongPtr;
256         }
257 };
258
259 ////////////////////////////////////////////////////////////////////////////////
260 ///  \class AllowReset
261 ///
262 ///  \ingroup  StrongPointerResetGroup
263 ///  Implementation of the ResetPolicy used by StrongPtr.  It allows reset and
264 ///   release under any circumstance.
265 ////////////////////////////////////////////////////////////////////////////////
266
267 template < class P >
268 struct AllowReset
269 {
270         inline bool OnReleaseAll( bool ) const
271         {
272                 return true;
273         }
274         inline bool OnResetAll( bool ) const
275         {
276                 return true;
277         }
278 };
279
280 ////////////////////////////////////////////////////////////////////////////////
281 ///  \class NeverReset
282 ///
283 ///  \ingroup  StrongPointerResetGroup
284 ///  Implementation of the ResetPolicy used by StrongPtr.  It forbids reset and
285 ///   release under any circumstance.
286 ////////////////////////////////////////////////////////////////////////////////
287
288 template < class P >
289 struct NeverReset
290 {
291         inline bool OnReleaseAll( bool ) const
292         {
293                 return false;
294         }
295         inline bool OnResetAll( bool ) const
296         {
297                 return false;
298         }
299 };
300
301 // ----------------------------------------------------------------------------
302
303 namespace Private
304 {
305
306 ////////////////////////////////////////////////////////////////////////////////
307 ///  \class TwoRefCountInfo
308 ///
309 ///  \ingroup  StrongPointerOwnershipGroup
310 ///   Implementation detail for reference counting strong and weak pointers.
311 ///   It maintains a void pointer and 2 reference counts.  Since it is just a
312 ///   class for managing implementation details, it is not intended to be used
313 ///   directly - which is why it is in a private namespace.  Each instance is a
314 ///   shared resource for all copointers, and there should be only one of these
315 ///   for each set of copointers.  This class is small, trivial, and inline.
316 ////////////////////////////////////////////////////////////////////////////////
317
318 class LOKI_EXPORT TwoRefCountInfo
319 {
320 public:
321
322         inline explicit TwoRefCountInfo( bool strong )
323                 : m_pointer( 0 )
324                 , m_strongCount( strong ? 1 : 0 )
325                 , m_weakCount( strong ? 0 : 1 )
326         {
327         }
328
329         inline TwoRefCountInfo( void *p, bool strong )
330                 : m_pointer( p )
331                 , m_strongCount( strong ? 1 : 0 )
332                 , m_weakCount( strong ? 0 : 1 )
333         {
334         }
335
336         inline ~TwoRefCountInfo( void )
337         {
338                 assert( 0 == m_strongCount );
339                 assert( 0 == m_weakCount );
340         }
341
342         inline bool HasStrongPointer( void ) const
343         {
344                 return ( 0 < m_strongCount );
345         }
346
347         inline bool HasWeakPointer( void ) const
348         {
349                 return ( 0 < m_weakCount );
350         }
351
352         inline void IncStrongCount( void )
353         {
354                 ++m_strongCount;
355         }
356
357         inline void IncWeakCount( void )
358         {
359                 ++m_weakCount;
360         }
361
362         inline bool DecStrongCount( void )
363         {
364                 assert( 0 < m_strongCount );
365                 --m_strongCount;
366                 const bool isZero = ( 0 == m_strongCount );
367                 return isZero;
368         }
369
370         inline void DecWeakCount( void )
371         {
372                 assert( 0 < m_weakCount );
373                 --m_weakCount;
374         }
375
376         inline void ZapPointer( void )
377         {
378                 m_pointer = 0;
379         }
380
381         void SetPointer( void *p )
382         {
383                 m_pointer = p;
384         }
385
386         inline void *GetPointer( void ) const
387         {
388                 return m_pointer;
389         }
390
391         inline void * &GetPointerRef( void ) const
392         {
393                 return const_cast< void * & >( m_pointer );
394         }
395
396 private:
397         /// Copy-constructor not implemented.
398         TwoRefCountInfo( const TwoRefCountInfo & );
399         /// Copy-assignment operator not implemented.
400         TwoRefCountInfo &operator = ( const TwoRefCountInfo & );
401
402         void *m_pointer;
403         unsigned int m_strongCount;
404         unsigned int m_weakCount;
405 };
406
407 ////////////////////////////////////////////////////////////////////////////////
408 ///  \class LockableTwoRefCountInfo
409 ///
410 ///  \ingroup  StrongPointerOwnershipGroup
411 ///   Implementation detail for thread-safe reference counting for strong and
412 ///   weak pointers.  It uses TwoRefCountInfo to manage the pointer and counts.
413 ///   All this does is provide a thread safety mechanism.  Since it is just a
414 ///   class for managing implementation details, it is not intended to be used
415 ///   directly - which is why it is in a private namespace.  Each instance is a
416 ///   shared resource for all copointers, and there should be only one of these
417 ///   for each set of copointers.  This class is small, trivial, and inline.
418 ///
419 ///  \note This class is not designed for use with a single-threaded model.
420 ///   Tests using a single-threaded model will not run properly, but tests in a
421 ///   multi-threaded model with either class-level-locking or object-level-locking
422 ///   do run properly.
423 ////////////////////////////////////////////////////////////////////////////////
424
425 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
426
427 class LOKI_EXPORT LockableTwoRefCountInfo
428         : private Loki::Private::TwoRefCountInfo
429 {
430 public:
431
432         inline explicit LockableTwoRefCountInfo( bool strong )
433                 : TwoRefCountInfo( strong )
434                 , m_Mutex()
435         {
436         }
437
438         LockableTwoRefCountInfo( void *p, bool strong )
439                 : TwoRefCountInfo( p, strong )
440                 , m_Mutex()
441         {
442         }
443
444         inline ~LockableTwoRefCountInfo( void )
445         {
446         }
447
448         inline void Lock( void ) const
449         {
450                 m_Mutex.Lock();
451         }
452
453         inline void Unlock( void ) const
454         {
455                 m_Mutex.Unlock();
456         }
457
458         inline bool HasStrongPointer( void ) const
459         {
460                 m_Mutex.Lock();
461                 const bool has = TwoRefCountInfo::HasStrongPointer();
462                 m_Mutex.Unlock();
463                 return has;
464         }
465
466         inline bool HasWeakPointer( void ) const
467         {
468                 m_Mutex.Lock();
469                 const bool has = TwoRefCountInfo::HasWeakPointer();
470                 m_Mutex.Unlock();
471                 return has;
472         }
473
474         inline void IncStrongCount( void )
475         {
476                 m_Mutex.Lock();
477                 TwoRefCountInfo::IncStrongCount();
478                 m_Mutex.Unlock();
479         }
480
481         inline void IncWeakCount( void )
482         {
483                 m_Mutex.Lock();
484                 TwoRefCountInfo::IncWeakCount();
485                 m_Mutex.Unlock();
486         }
487
488         inline bool DecStrongCount( void )
489         {
490                 m_Mutex.Lock();
491                 const bool isZero = TwoRefCountInfo::DecStrongCount();
492                 m_Mutex.Unlock();
493                 return isZero;
494         }
495
496         inline void DecWeakCount( void )
497         {
498                 m_Mutex.Lock();
499                 TwoRefCountInfo::DecWeakCount();
500                 m_Mutex.Unlock();
501         }
502
503         inline void ZapPointer( void )
504         {
505                 m_Mutex.Lock();
506                 TwoRefCountInfo::ZapPointer();
507                 m_Mutex.Unlock();
508         }
509
510         void SetPointer( void *p )
511         {
512                 m_Mutex.Lock();
513                 TwoRefCountInfo::SetPointer( p );
514                 m_Mutex.Unlock();
515         }
516
517         inline void *GetPointer( void ) const
518         {
519                 return TwoRefCountInfo::GetPointer();
520         }
521
522         inline void * &GetPointerRef( void ) const
523         {
524                 return TwoRefCountInfo::GetPointerRef();
525         }
526
527 private:
528         /// Default constructor is not available.
529         LockableTwoRefCountInfo( void );
530         /// Copy constructor is not available.
531         LockableTwoRefCountInfo( const LockableTwoRefCountInfo & );
532         /// Copy-assignment operator is not available.
533         LockableTwoRefCountInfo &operator = ( const LockableTwoRefCountInfo & );
534
535         mutable LOKI_DEFAULT_MUTEX m_Mutex;
536 };
537
538 #endif // if object-level-locking or class-level-locking
539
540 } // end namespace Private
541
542 ////////////////////////////////////////////////////////////////////////////////
543 ///  \class TwoRefCounts
544 ///
545 ///  \ingroup  StrongPointerOwnershipGroup
546 ///   This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
547 ///   shared instance of TwoRefCountInfo.  This is the default policy for
548 ///   OwnershipPolicy.  Some functions are trivial enough to be inline, while
549 ///   others are implemented elsewhere.  It is not thread safe, and is intended
550 ///   for single-threaded environments.
551 ////////////////////////////////////////////////////////////////////////////////
552
553 class LOKI_EXPORT TwoRefCounts
554 {
555 protected:
556
557         explicit TwoRefCounts( bool strong );
558
559         TwoRefCounts( const void *p, bool strong );
560
561         TwoRefCounts( const TwoRefCounts &rhs, bool strong ) :
562                 m_counts( rhs.m_counts )
563         {
564                 Increment( strong );
565         }
566
567         /** The destructor does not need to do anything since the call to
568          ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
569          this dtor would have done.
570          */
571         inline ~TwoRefCounts( void ) {}
572
573         inline bool Release( bool strong )
574         {
575                 return Decrement( strong );
576         }
577
578         bool HasStrongPointer( void ) const
579         {
580                 return m_counts->HasStrongPointer();
581         }
582
583         void Swap( TwoRefCounts &rhs );
584
585         void SetPointer( void *p )
586         {
587                 m_counts->SetPointer( p );
588         }
589
590         void ZapPointer( void );
591
592         inline void * &GetPointerRef( void ) const
593         {
594                 return m_counts->GetPointerRef();
595         }
596
597         inline void *GetPointer( void ) const
598         {
599                 return m_counts->GetPointer();
600         }
601
602 private:
603         TwoRefCounts( void );
604         TwoRefCounts &operator = ( const TwoRefCounts & );
605
606         void Increment( bool strong );
607
608         bool Decrement( bool strong );
609
610         /// Pointer to all shared data.
611         Loki::Private::TwoRefCountInfo *m_counts;
612 };
613
614 ////////////////////////////////////////////////////////////////////////////////
615 ///  \class LockableTwoRefCounts
616 ///
617 ///  \ingroup  StrongPointerOwnershipGroup
618 ///   This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
619 ///   shared instance of LockableTwoRefCountInfo.  It behaves very similarly to
620 ///   TwoRefCounts, except that it provides thread-safety.  Some functions are
621 ///   trivial enough to be inline, while others are implemented elsewhere.
622 ///
623 ///  \note This class is not designed for use with a single-threaded model.
624 ///   Tests using a single-threaded model will not run properly, but tests in a
625 ///   multi-threaded model with either class-level-locking or object-level-locking
626 ///   do run properly.
627 ////////////////////////////////////////////////////////////////////////////////
628
629 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
630
631 class LOKI_EXPORT LockableTwoRefCounts
632 {
633         typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
634
635 protected:
636
637         explicit LockableTwoRefCounts( bool strong )
638                 : m_counts( NULL )
639         {
640                 void *temp = ThreadSafePointerAllocator::operator new(
641                                  sizeof(Loki::Private::LockableTwoRefCountInfo) );
642 #ifdef DO_EXTRA_LOKI_TESTS
643                 assert( temp != 0 );
644 #endif
645                 m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
646         }
647
648         LockableTwoRefCounts( const void *p, bool strong )
649                 : m_counts( NULL )
650         {
651                 void *temp = ThreadSafePointerAllocator::operator new(
652                                  sizeof(Loki::Private::LockableTwoRefCountInfo) );
653 #ifdef DO_EXTRA_LOKI_TESTS
654                 assert( temp != 0 );
655 #endif
656                 void *p2 = const_cast< void * >( p );
657                 m_counts = new ( temp )
658                 Loki::Private::LockableTwoRefCountInfo( p2, strong );
659         }
660
661         LockableTwoRefCounts( const LockableTwoRefCounts &rhs, bool strong ) :
662                 m_counts( rhs.m_counts )
663         {
664                 Increment( strong );
665         }
666
667         /** The destructor does not need to do anything since the call to
668          ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
669          this dtor would have done.
670          */
671         inline ~LockableTwoRefCounts( void ) {}
672
673         inline void Lock( void ) const
674         {
675                 m_counts->Lock();
676         }
677
678         inline void Unlock( void ) const
679         {
680                 m_counts->Unlock();
681         }
682
683         inline bool Release( bool strong )
684         {
685                 return Decrement( strong );
686         }
687
688         void Increment( bool strong )
689         {
690                 if ( strong )
691                 {
692                         m_counts->IncStrongCount();
693                 }
694                 else
695                 {
696                         m_counts->IncWeakCount();
697                 }
698         }
699
700         bool Decrement( bool strong )
701         {
702                 bool noStrongPointers = false;
703                 if ( strong )
704                 {
705                         noStrongPointers = m_counts->DecStrongCount();
706                 }
707                 else
708                 {
709                         m_counts->DecWeakCount();
710                         noStrongPointers = !m_counts->HasStrongPointer();
711                 }
712                 return noStrongPointers;
713         }
714
715         bool HasStrongPointer( void ) const
716         {
717                 return m_counts->HasStrongPointer();
718         }
719
720         void Swap( LockableTwoRefCounts &rhs )
721         {
722                 std::swap( m_counts, rhs.m_counts );
723         }
724
725         void SetPointer( void *p )
726         {
727                 m_counts->SetPointer( p );
728         }
729
730         void ZapPointer( void )
731         {
732 #ifdef DO_EXTRA_LOKI_TESTS
733                 assert( !m_counts->HasStrongPointer() );
734 #endif
735                 if ( m_counts->HasWeakPointer() )
736                 {
737                         m_counts->ZapPointer();
738                 }
739                 else
740                 {
741                         ThreadSafePointerAllocator::operator delete ( m_counts,
742                                 sizeof(Loki::Private::LockableTwoRefCountInfo) );
743                         m_counts = NULL;
744                 }
745         }
746
747         inline void *GetPointer( void ) const
748         {
749                 return m_counts->GetPointer();
750         }
751
752         inline void * &GetPointerRef( void ) const
753         {
754                 return m_counts->GetPointerRef();
755         }
756
757 private:
758         LockableTwoRefCounts( void );
759         LockableTwoRefCounts &operator = ( const LockableTwoRefCounts & );
760
761         /// Pointer to all shared data.
762         Loki::Private::LockableTwoRefCountInfo *m_counts;
763 };
764
765 #endif // if object-level-locking or class-level-locking
766
767 ////////////////////////////////////////////////////////////////////////////////
768 ///  \class TwoRefLinks
769 ///
770 ///  \ingroup  StrongPointerOwnershipGroup
771 ///   This implementation of StrongPtr's OwnershipPolicy uses a doubly-linked
772 ///   cycle of copointers to a shared object. Some functions are trivial enough
773 ///   to be inline, while others are implemented in elsewhere.  It is not thread
774 ///   safe, and is intended for single-threaded environments.
775 ////////////////////////////////////////////////////////////////////////////////
776
777 class LOKI_EXPORT TwoRefLinks
778 {
779 protected:
780
781         inline explicit TwoRefLinks( bool strong )
782                 : m_pointer( 0 )
783                 , m_strong( strong )
784         {
785                 m_prev = m_next = this;
786         }
787
788         TwoRefLinks( const void *p, bool strong );
789
790         TwoRefLinks( const TwoRefLinks &rhs, bool strong );
791
792         bool Release( bool strong );
793
794         void Swap( TwoRefLinks &rhs );
795
796         bool Merge( TwoRefLinks &rhs );
797
798         bool HasStrongPointer( void ) const;
799
800         inline void ZapPointer( void )
801         {
802                 ZapAllNodes();
803         }
804
805         void SetPointer( void *p );
806
807         inline void *GetPointer( void ) const
808         {
809                 return m_pointer;
810         }
811
812         inline void * &GetPointerRef( void ) const
813         {
814                 return const_cast< void * & >( m_pointer );
815         }
816
817 private:
818         static unsigned int CountPrevCycle( const TwoRefLinks *pThis );
819         static unsigned int CountNextCycle( const TwoRefLinks *pThis );
820
821         /// Not implemented.
822         TwoRefLinks( void );
823         /// Not implemented.
824         TwoRefLinks &operator = ( const TwoRefLinks & );
825
826         bool HasPrevNode( const TwoRefLinks *p ) const;
827         bool HasNextNode( const TwoRefLinks *p ) const;
828         bool AllNodesHaveSamePointer( void ) const;
829         void ZapAllNodes( void );
830
831         void *m_pointer;
832         mutable TwoRefLinks *m_prev;
833         mutable TwoRefLinks *m_next;
834         const bool m_strong;
835 };
836
837 ////////////////////////////////////////////////////////////////////////////////
838 ///  \class StrongPtr
839 ///
840 ///  \ingroup SmartPointerGroup
841 ///
842 ///  \param Strong           default = true,
843 ///  \param OwnershipPolicy  default = TwoRefCounts,
844 ///  \param ConversionPolicy default = DisallowConversion,
845 ///  \param CheckingPolicy   default = AssertCheck,
846 ///  \param ResetPolicy      default = CantResetWithStrong,
847 ///  \param DeletePolicy     default = DeleteSingle
848 ///  \param ConstnessPolicy  default = LOKI_DEFAULT_CONSTNESS
849 ////////////////////////////////////////////////////////////////////////////////
850
851 template
852 <
853 typename T,
854          bool Strong = true,
855          class OwnershipPolicy = Loki::TwoRefCounts,
856          class ConversionPolicy = Loki::DisallowConversion,
857          template < class > class CheckingPolicy = Loki::AssertCheck,
858          template < class > class ResetPolicy = Loki::CantResetWithStrong,
859          template < class > class DeletePolicy = Loki::DeleteSingle,
860          template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
861          >
862 class StrongPtr
863         : public OwnershipPolicy
864         , public ConversionPolicy
865         , public CheckingPolicy< T * >
866         , public ResetPolicy< T >
867         , public DeletePolicy< T >
868 {
869         typedef ConversionPolicy CP;
870         typedef CheckingPolicy< T * > KP;
871         typedef ResetPolicy< T > RP;
872         typedef DeletePolicy< T > DP;
873
874 public:
875
876         typedef OwnershipPolicy OP;
877
878         typedef T *StoredType;     // the type of the pointer
879         typedef T *PointerType;    // type returned by operator->
880         typedef T &ReferenceType;  // type returned by operator*
881
882         typedef typename ConstnessPolicy< T >::Type *ConstPointerType;
883         typedef typename ConstnessPolicy< T >::Type &ConstReferenceType;
884
885 private:
886         struct NeverMatched {};
887
888 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
889         typedef typename Select< CP::allow, const StoredType &, NeverMatched>::Result ImplicitArg;
890         typedef typename Select<!CP::allow, const StoredType &, NeverMatched>::Result ExplicitArg;
891 #else
892         typedef const StoredType &ImplicitArg;
893         typedef typename Select<false, const StoredType &, NeverMatched>::Result ExplicitArg;
894 #endif
895
896 public:
897
898         StrongPtr( void ) : OP( Strong )
899         {
900                 KP::OnDefault( GetPointer() );
901         }
902
903         explicit StrongPtr( ExplicitArg p ) : OP( p, Strong )
904         {
905                 KP::OnInit( GetPointer() );
906         }
907
908         StrongPtr( ImplicitArg p ) : OP( p, Strong )
909         {
910                 KP::OnInit( GetPointer() );
911         }
912
913         StrongPtr( const StrongPtr &rhs )
914                 : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs )
915         {
916         }
917
918         template
919         <
920         typename T1,
921                  bool S1,
922                  class OP1,
923                  class CP1,
924                  template < class > class KP1,
925                  template < class > class RP1,
926                  template < class > class DP1,
927                  template < class > class CNP1
928                  >
929         StrongPtr(
930             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
931                 : OP( rhs, Strong )
932         {
933         }
934
935         template
936         <
937         typename T1,
938                  bool S1,
939                  class OP1,
940                  class CP1,
941                  template < class > class KP1,
942                  template < class > class RP1,
943                  template < class > class DP1,
944                  template < class > class CNP1
945                  >
946         StrongPtr(
947             StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
948                 : OP( rhs, Strong )
949         {
950         }
951
952         StrongPtr( RefToValue< StrongPtr > rhs )
953                 : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs )
954         {
955         }
956
957         operator RefToValue< StrongPtr >( void )
958         {
959                 return RefToValue< StrongPtr >( *this );
960         }
961
962         StrongPtr &operator = ( const StrongPtr &rhs )
963         {
964                 if ( GetPointer() != rhs.GetPointer() )
965                 {
966                         StrongPtr temp( rhs );
967                         temp.Swap( *this );
968                 }
969                 return *this;
970         }
971
972         StrongPtr &operator = ( T *p )
973         {
974                 if ( GetPointer() != p )
975                 {
976                         StrongPtr temp( p );
977                         Swap( temp );
978                 }
979                 return *this;
980         }
981
982         template
983         <
984         typename T1,
985                  bool S1,
986                  class OP1,
987                  class CP1,
988                  template < class > class KP1,
989                  template < class > class RP1,
990                  template < class > class DP1,
991                  template < class > class CNP1
992                  >
993         StrongPtr &operator = (
994             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
995         {
996                 if ( !rhs.Equals( GetPointer() ) )
997                 {
998                         StrongPtr temp( rhs );
999                         temp.Swap( *this );
1000                 }
1001                 return *this;
1002         }
1003
1004         bool IsStrong( void ) const
1005         {
1006                 return Strong;
1007         }
1008
1009         void Swap( StrongPtr &rhs )
1010         {
1011                 OP::Swap( rhs );
1012                 CP::Swap( rhs );
1013                 KP::Swap( rhs );
1014                 DP::Swap( rhs );
1015         }
1016
1017         ~StrongPtr()
1018         {
1019                 if ( OP::Release( Strong ) )
1020                 {
1021                         // Must zap the pointer before deleteing the object. Otherwise a
1022                         // cycle of weak pointers will lead to recursion, which leads to
1023                         // to deleting the shared object multiple times, which leads to
1024                         // undefined behavior.  Therefore, this must get pointer before
1025                         // zapping it, and then delete the temp pointer.
1026                         T *p = GetPointer();
1027                         OP::ZapPointer();
1028                         if ( p != 0 )
1029                         {
1030                                 DP::Delete( p );
1031                         }
1032                 }
1033         }
1034
1035 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1036
1037         // old non standard in class definition of friends
1038         friend bool ReleaseAll( StrongPtr &sp,
1039                                 typename StrongPtr::StoredType &p )
1040         {
1041                 if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1042                 {
1043                         return false;
1044                 }
1045                 p = sp.GetPointer();
1046                 sp.OP::SetPointer( sp.DP::Default() );
1047                 return true;
1048         }
1049
1050         friend bool ResetAll( StrongPtr &sp,
1051                               typename StrongPtr::StoredType p )
1052         {
1053                 if ( sp.OP::GetPointer() == p )
1054                 {
1055                         return true;
1056                 }
1057                 if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1058                 {
1059                         return false;
1060                 }
1061                 sp.DP::Delete( sp.GetPointer() );
1062                 sp.OP::SetPointer( p );
1063                 return true;
1064         }
1065
1066 #else
1067
1068         template
1069         <
1070         typename T1,
1071                  bool S1,
1072                  class OP1,
1073                  class CP1,
1074                  template < class > class KP1,
1075                  template < class > class RP1,
1076                  template < class > class DP1,
1077                  template < class > class CNP1
1078                  >
1079         friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
1080                                 typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType &p );
1081
1082
1083         template
1084         <
1085         typename T1,
1086                  bool S1,
1087                  class OP1,
1088                  class CP1,
1089                  template < class > class KP1,
1090                  template < class > class RP1,
1091                  template < class > class DP1,
1092                  template < class > class CNP1
1093                  >
1094         friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
1095                               typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p );
1096
1097 #endif
1098
1099
1100         /** Merges ownership of two StrongPtr's that point to same shared object
1101           but are not copointers.  Requires Merge function in OwnershipPolicy.
1102           \return True for success, false if not pointer to same object.
1103          */
1104         template
1105         <
1106         typename T1,
1107                  bool S1,
1108                  class OP1,
1109                  class CP1,
1110                  template < class > class KP1,
1111                  template < class > class RP1,
1112                  template < class > class DP1,
1113                  template < class > class CNP1
1114                  >
1115         bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
1116         {
1117                 if ( OP::GetPointer() != rhs.OP::GetPointer() )
1118                 {
1119                         return false;
1120                 }
1121                 return OP::Merge( rhs );
1122         }
1123
1124         /** Locks StrongPtr so other threads can't affect pointer.  Requires the
1125          OwnershipPolicy to have Lock function.
1126          */
1127         void Lock( void )
1128         {
1129                 OP::Lock();
1130         }
1131
1132         /** Unlocks StrongPtr so other threads can affect pointer.  Requires the
1133          OwnershipPolicy to have Unlock function.
1134          */
1135         void Unlock( void )
1136         {
1137                 OP::Unlock();
1138         }
1139
1140         PointerType operator -> ()
1141         {
1142                 KP::OnDereference( GetPointer() );
1143                 return GetPointer();
1144         }
1145
1146         ConstPointerType operator -> () const
1147         {
1148                 KP::OnDereference( GetPointer() );
1149                 return GetPointer();
1150         }
1151
1152         ReferenceType operator * ()
1153         {
1154                 KP::OnDereference( GetPointer() );
1155                 return * GetPointer();
1156         }
1157
1158         ConstReferenceType operator * () const
1159         {
1160                 KP::OnDereference( GetPointer() );
1161                 return * GetPointer();
1162         }
1163
1164         /// Helper function which can be called to avoid exposing GetPointer function.
1165         template < class T1 >
1166         bool Equals( const T1 *p ) const
1167         {
1168                 return ( GetPointer() == p );
1169         }
1170
1171         /// Helper function which can be called to avoid exposing GetPointer function.
1172         template < class T1 >
1173         bool LessThan( const T1 *p ) const
1174         {
1175                 return ( GetPointer() < p );
1176         }
1177
1178         /// Helper function which can be called to avoid exposing GetPointer function.
1179         template < class T1 >
1180         bool GreaterThan( const T1 *p ) const
1181         {
1182                 return ( GetPointer() > p );
1183         }
1184
1185         /// Equality comparison operator is templated to handle ambiguity.
1186         template
1187         <
1188         typename T1,
1189                  bool S1,
1190                  class OP1,
1191                  class CP1,
1192                  template < class > class KP1,
1193                  template < class > class RP1,
1194                  template < class > class DP1,
1195                  template < class > class CNP1
1196                  >
1197         bool operator == (
1198             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1199         {
1200                 return ( rhs.Equals( GetPointer() ) );
1201         }
1202
1203         /// Inequality comparison operator is templated to handle ambiguity.
1204         template
1205         <
1206         typename T1,
1207                  bool S1,
1208                  class OP1,
1209                  class CP1,
1210                  template < class > class KP1,
1211                  template < class > class RP1,
1212                  template < class > class DP1,
1213                  template < class > class CNP1
1214                  >
1215         bool operator != (
1216             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1217         {
1218                 return !( rhs.Equals( GetPointer() ) );
1219         }
1220
1221         /// Less-than comparison operator is templated to handle ambiguity.
1222         template
1223         <
1224         typename T1,
1225                  bool S1,
1226                  class OP1,
1227                  class CP1,
1228                  template < class > class KP1,
1229                  template < class > class RP1,
1230                  template < class > class DP1,
1231                  template < class > class CNP1
1232                  >
1233         bool operator < (
1234             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1235         {
1236                 return ( rhs.GreaterThan( GetPointer() ) );
1237         }
1238
1239         /// Greater-than comparison operator is templated to handle ambiguity.
1240         template
1241         <
1242         typename T1,
1243                  bool S1,
1244                  class OP1,
1245                  class CP1,
1246                  template < class > class KP1,
1247                  template < class > class RP1,
1248                  template < class > class DP1,
1249                  template < class > class CNP1
1250                  >
1251         inline bool operator > (
1252             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1253         {
1254                 return ( rhs.LessThan( GetPointer() ) );
1255         }
1256
1257         /// Less-than-or-equal-to operator is templated to handle ambiguity.
1258         template
1259         <
1260         typename T1,
1261                  bool S1,
1262                  class OP1,
1263                  class CP1,
1264                  template < class > class KP1,
1265                  template < class > class RP1,
1266                  template < class > class DP1,
1267                  template < class > class CNP1
1268                  >
1269         inline bool operator <= (
1270             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1271         {
1272                 return !( rhs.LessThan( GetPointer() ) );
1273         }
1274
1275         /// Greater-than-or-equal-to operator is templated to handle ambiguity.
1276         template
1277         <
1278         typename T1,
1279                  bool S1,
1280                  class OP1,
1281                  class CP1,
1282                  template < class > class KP1,
1283                  template < class > class RP1,
1284                  template < class > class DP1,
1285                  template < class > class CNP1
1286                  >
1287         inline bool operator >= (
1288             const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1289         {
1290                 return !( rhs.GreaterThan( GetPointer() ) );
1291         }
1292
1293         inline bool operator ! () const // Enables "if ( !sp ) ..."
1294         {
1295                 return ( 0 == OP::GetPointer() );
1296         }
1297
1298 protected:
1299
1300         inline PointerType GetPointer( void )
1301         {
1302                 return reinterpret_cast< PointerType >( OP::GetPointer() );
1303         }
1304
1305         inline ConstPointerType GetPointer( void ) const
1306         {
1307                 return reinterpret_cast< ConstPointerType >( OP::GetPointer() );
1308         }
1309
1310 private:
1311
1312         inline ReferenceType GetPointerRef( void )
1313         {
1314                 return reinterpret_cast< ReferenceType >( OP::GetPointerRef() );
1315         }
1316
1317         inline ConstReferenceType GetPointerRef( void ) const
1318         {
1319                 return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() );
1320         }
1321
1322         // Helper for enabling 'if (sp)'
1323         struct Tester
1324         {
1325                 Tester(int) {}
1326                 void dummy() {}
1327         };
1328
1329         typedef void (Tester::*unspecified_boolean_type_)();
1330
1331         typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result
1332         unspecified_boolean_type;
1333
1334 public:
1335         // enable 'if (sp)'
1336         operator unspecified_boolean_type() const
1337         {
1338                 return !*this ? 0 : &Tester::dummy;
1339         }
1340
1341 private:
1342         // Helper for disallowing automatic conversion
1343         struct Insipid
1344         {
1345                 Insipid(PointerType) {}
1346         };
1347
1348         typedef typename Select< CP::allow, PointerType, Insipid >::Result
1349         AutomaticConversionResult;
1350
1351 public:
1352         operator AutomaticConversionResult() const
1353         {
1354                 return GetPointer();
1355         }
1356
1357 };
1358
1359 // ----------------------------------------------------------------------------
1360
1361 // friend functions
1362
1363 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1364
1365 template
1366 <
1367 typename U,
1368          typename T,
1369          bool S,
1370          class OP,
1371          class CP,
1372          template < class > class KP,
1373          template < class > class RP,
1374          template < class > class DP,
1375          template < class > class CNP
1376          >
1377 bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
1378                  typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType &p )
1379 {
1380         if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1381         {
1382                 return false;
1383         }
1384         p = sp.GetPointer();
1385         sp.OP::SetPointer( sp.DP<T>::Default() );
1386         return true;
1387 }
1388
1389 template
1390 <
1391 typename U,
1392          typename T,
1393          bool S,
1394          class OP,
1395          class CP,
1396          template < class > class KP,
1397          template < class > class RP,
1398          template < class > class DP,
1399          template < class > class CNP
1400          >
1401 bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
1402                typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p )
1403 {
1404         if ( sp.OP::GetPointer() == p )
1405         {
1406                 return true;
1407         }
1408         if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1409         {
1410                 return false;
1411         }
1412         sp.DP<T>::Delete( sp.GetPointer() );
1413         sp.OP::SetPointer( p );
1414         return true;
1415 }
1416 #endif
1417
1418
1419 // free comparison operators for class template StrongPtr
1420
1421 ///  operator== for lhs = StrongPtr, rhs = raw pointer
1422 ///  \ingroup SmartPointerGroup
1423 template
1424 <
1425 typename U,
1426          typename T,
1427          bool S,
1428          class OP,
1429          class CP,
1430          template < class > class KP,
1431          template < class > class RP,
1432          template < class > class DP,
1433          template < class > class CNP
1434          >
1435 inline bool operator == (
1436     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1437 {
1438         return ( lhs.Equals( rhs ) );
1439 }
1440
1441 ///  operator== for lhs = raw pointer, rhs = StrongPtr
1442 ///  \ingroup SmartPointerGroup
1443 template
1444 <
1445 typename U,
1446          typename T,
1447          bool S,
1448          class OP,
1449          class CP,
1450          template < class > class KP,
1451          template < class > class RP,
1452          template < class > class DP,
1453          template < class > class CNP
1454          >
1455 inline bool operator == ( U *lhs,
1456                           const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1457 {
1458         return ( rhs.Equals( lhs ) );
1459 }
1460
1461 ///  operator!= for lhs = StrongPtr, rhs = raw pointer
1462 ///  \ingroup SmartPointerGroup
1463 template
1464 <
1465 typename U,
1466          typename T,
1467          bool S,
1468          class OP,
1469          class CP,
1470          template < class > class KP,
1471          template < class > class RP,
1472          template < class > class DP,
1473          template < class > class CNP
1474          >
1475 inline bool operator != (
1476     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1477 {
1478         return !( lhs.Equals( rhs ) );
1479 }
1480
1481 ///  operator!= for lhs = raw pointer, rhs = StrongPtr
1482 ///  \ingroup SmartPointerGroup
1483 template
1484 <
1485 typename U,
1486          typename T,
1487          bool S,
1488          class OP,
1489          class CP,
1490          template < class > class KP,
1491          template < class > class RP,
1492          template < class > class DP,
1493          template < class > class CNP
1494          >
1495 inline bool operator != ( U *lhs,
1496                           const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1497 {
1498         return !( rhs.Equals( lhs ) );
1499 }
1500
1501 ///  operator< for lhs = StrongPtr, rhs = raw pointer
1502 ///  \ingroup SmartPointerGroup
1503 template
1504 <
1505 typename U,
1506          typename T,
1507          bool S,
1508          class OP,
1509          class CP,
1510          template < class > class KP,
1511          template < class > class RP,
1512          template < class > class DP,
1513          template < class > class CNP
1514          >
1515 inline bool operator < (
1516     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1517 {
1518         return ( lhs.LessThan( rhs ) );
1519 }
1520
1521 ///  operator< for lhs = raw pointer, rhs = StrongPtr
1522 ///  \ingroup SmartPointerGroup
1523 template
1524 <
1525 typename U,
1526          typename T,
1527          bool S,
1528          class OP,
1529          class CP,
1530          template < class > class KP,
1531          template < class > class RP,
1532          template < class > class DP,
1533          template < class > class CNP
1534          >
1535 inline bool operator < ( U *lhs,
1536                          const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1537 {
1538         return ( rhs.GreaterThan( lhs ) );
1539 }
1540
1541 //  operator> for lhs = StrongPtr, rhs = raw pointer
1542 ///  \ingroup SmartPointerGroup
1543 template
1544 <
1545 typename U,
1546          typename T,
1547          bool S,
1548          class OP,
1549          class CP,
1550          template < class > class KP,
1551          template < class > class RP,
1552          template < class > class DP,
1553          template < class > class CNP
1554          >
1555 inline bool operator > (
1556     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1557 {
1558         return ( lhs.GreaterThan( rhs ) );
1559 }
1560
1561 ///  operator> for lhs = raw pointer, rhs = StrongPtr
1562 ///  \ingroup SmartPointerGroup
1563 template
1564 <
1565 typename U,
1566          typename T,
1567          bool S,
1568          class OP,
1569          class CP,
1570          template < class > class KP,
1571          template < class > class RP,
1572          template < class > class DP,
1573          template < class > class CNP
1574          >
1575 inline bool operator > ( U *lhs,
1576                          const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1577 {
1578         return ( rhs.LessThan( lhs ) );
1579 }
1580
1581 ///  operator<= for lhs = StrongPtr, rhs = raw pointer
1582 ///  \ingroup SmartPointerGroup
1583 template
1584 <
1585 typename U,
1586          typename T,
1587          bool S,
1588          class OP,
1589          class CP,
1590          template < class > class KP,
1591          template < class > class RP,
1592          template < class > class DP,
1593          template < class > class CNP
1594          >
1595 inline bool operator <= (
1596     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1597 {
1598         return !( lhs.GreaterThan( rhs ) );
1599 }
1600
1601 ///  operator<= for lhs = raw pointer, rhs = StrongPtr
1602 ///  \ingroup SmartPointerGroup
1603 template
1604 <
1605 typename U,
1606          typename T,
1607          bool S,
1608          class OP,
1609          class CP,
1610          template < class > class KP,
1611          template < class > class RP,
1612          template < class > class DP,
1613          template < class > class CNP
1614          >
1615 inline bool operator <= ( U *lhs,
1616                           const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1617 {
1618         return !( rhs.LessThan( lhs ) );
1619 }
1620
1621 ///  operator>= for lhs = StrongPtr, rhs = raw pointer
1622 ///  \ingroup SmartPointerGroup
1623 template
1624 <
1625 typename U,
1626          typename T,
1627          bool S,
1628          class OP,
1629          class CP,
1630          template < class > class KP,
1631          template < class > class RP,
1632          template < class > class DP,
1633          template < class > class CNP
1634          >
1635 inline bool operator >= (
1636     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U *rhs )
1637 {
1638         return !( lhs.LessThan( rhs ) );
1639 }
1640
1641 ///  operator>= for lhs = raw pointer, rhs = StrongPtr
1642 ///  \ingroup SmartPointerGroup
1643 template
1644 <
1645 typename U,
1646          typename T,
1647          bool S,
1648          class OP,
1649          class CP,
1650          template < class > class KP,
1651          template < class > class RP,
1652          template < class > class DP,
1653          template < class > class CNP
1654          >
1655 inline bool operator >= ( U *lhs,
1656                           const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1657 {
1658         return !( rhs.GreaterThan( lhs ) );
1659 }
1660
1661 } // namespace Loki
1662
1663 namespace std
1664 {
1665 ////////////////////////////////////////////////////////////////////////////////
1666 ///  specialization of std::less for StrongPtr
1667 ///  \ingroup SmartPointerGroup
1668 ////////////////////////////////////////////////////////////////////////////////
1669 template
1670 <
1671 typename T,
1672          bool S,
1673          class OP,
1674          class CP,
1675          template < class > class KP,
1676          template < class > class RP,
1677          template < class > class DP,
1678          template < class > class CNP
1679          >
1680 struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > >
1681                 : public binary_function<
1682                 Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >,
1683                 Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool >
1684 {
1685         bool operator () (
1686             const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs,
1687             const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const
1688         {
1689                 return ( lhs < rhs );
1690         }
1691 };
1692 }
1693
1694 ////////////////////////////////////////////////////////////////////////////////
1695
1696 #endif // end file guardian
1697