Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / ETL / tags / ETL_0_04_10_rc2 / ETL / _handle.h
1 /* === E T L =============================================================== */
2 /*!     \file _handle.h
3 **      $Id$
4 **      \brief Template Object Handle Implementation
5 **      \internal
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 **
21 **      \note
22 **              This is an internal header file, included by other ETL headers.
23 **              You should not attempt to use it directly.
24 */
25 /* ========================================================================= */
26
27 /* === S T A R T =========================================================== */
28
29 #ifndef __ETL__HANDLE_H
30 #define __ETL__HANDLE_H
31
32 /* === H E A D E R S ======================================================= */
33
34 #include <cassert>
35
36 /* === M A C R O S ========================================================= */
37
38 /* === T Y P E D E F S ===================================================== */
39
40 #define ETL_SELF_DELETING_SHARED_OBJECT
41
42 /* === C L A S S E S & S T R U C T S ======================================= */
43
44 #ifdef NDEBUG
45 #define assert_cast             static_cast
46 #else
47 #define assert_cast             dynamic_cast
48 #endif
49
50
51 _ETL_BEGIN_NAMESPACE
52
53 // Forward Declarations
54 template <class T> class handle;
55 template <class T> class loose_handle;
56 template <class T> class rhandle;
57
58
59 // ========================================================================
60 /*!     \class  shared_object _handle.h ETL/handle
61 **      \brief  Shared Object Base Class
62 **      \see handle, loose_handle
63 **      \writeme
64 */
65 class shared_object
66 {
67 private:
68         mutable int refcount;
69
70 protected:
71         shared_object():refcount(0) { }
72
73 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
74         virtual ~shared_object() { }
75 #else
76         ~shared_object() { }
77 #endif
78
79 public:
80         void ref()const
81                 { assert(refcount>=0); refcount++; }
82
83         //! Returns \c false if object needs to be deleted
84         bool unref()const
85         {
86                 assert(refcount>0);
87
88                 refcount--;
89
90                 if(refcount==0) {
91 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
92                         refcount=-666;
93                         delete this;
94 #endif
95                         return false;
96                 }
97
98                 return true;
99         }
100
101         int count()const
102                 { return refcount; }
103 }; // END of class shared_object
104
105 // ========================================================================
106 /*!     \class  virtual_shared_object _handle.h ETL/handle
107 **      \brief  Virtual Shared Object Base Class
108 **      \see handle, loose_handle
109 **      \writeme
110 */
111 class virtual_shared_object
112 {
113 protected:
114         virtual_shared_object() { }
115 public:
116         virtual ~virtual_shared_object()=0;
117         virtual void ref()const=0;
118         virtual bool unref()const=0;
119         virtual int count()const=0;
120         virtual virtual_shared_object *clone()=0;
121 }; // END of class virtual_shared_object
122
123 // ========================================================================
124 /*!     \class  handle _handle.h        ETL/handle
125 **      \brief  Object Handle
126 **      \see shared_object, loose_handle
127 **      \writeme
128 */
129 template <class T>
130 class handle
131 {
132 public:
133
134         typedef T value_type;
135         typedef T& reference;
136         typedef const T& const_reference;
137         typedef T* pointer;
138         typedef const T* const_pointer;
139         typedef int count_type;
140         typedef int size_type;
141
142 protected:
143         value_type *obj;                //!< Pointer to object
144
145 public:
146
147         //! Default constructor - empty handle
148         handle():obj(NULL) {}
149
150         //! Constructor that constructs from a pointer to new object
151         handle(pointer x):obj(x)
152         {
153                 if(obj)
154                         obj->ref();
155         }
156
157         //! Default copy constructor
158         handle(const handle<value_type> &x):obj(x.get())
159         {
160                 if(obj)
161                         obj->ref();
162         }
163
164         //! Handle is released on deletion
165         ~handle() { detach(); }
166
167         //! Template Assignment operator
168         /*! \note This class may not be necessary, and may be removed
169         **              at some point in the future.
170         */
171         /*
172         template <class U> handle<value_type> &
173         operator=(const handle<U> &x)
174         {
175                 if(x.get()==obj)
176                         return *this;
177
178                 detach();
179
180                 obj=static_cast<value_type*>(x.get());
181                 if(obj)obj->ref();
182                 return *this;
183         }
184         */
185
186         //! Assignment operator
187         handle<value_type> &
188         operator=(const handle<value_type> &x)
189         {
190                 if(x.get()==obj)
191                         return *this;
192
193                 detach();
194
195                 obj=x.get();
196                 if(obj)obj->ref();
197                 return *this;
198         }
199
200         //! Swaps the values of two handles without reference counts
201         handle<value_type> &
202         swap(handle<value_type> &x)
203         {
204                 pointer ptr=x.obj;
205                 x.obj=x.get();
206                 obj=ptr;
207                 return *this;
208         }
209
210         //! Handle detach procedure
211         /*! unref()'s the object and sets the internal object pointer to \c NULL */
212         void
213         detach()
214         {
215                 pointer xobj(obj);
216                 obj=0;
217 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
218                 if(xobj)
219                         xobj->unref();
220 #else
221                 if(xobj && !xobj->unref())
222                         delete xobj;
223 #endif
224         }
225
226         // This will be reintroduced with a new function
227         //void release() { detach(); }
228
229         void reset() { detach(); }
230
231         bool empty()const { return obj==0; }
232
233         //! Creates a new instance of a T object and puts it in the handle.
234         /*! Uses the default constructor */
235         void spawn() { operator=(handle(new T())); }
236
237         handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
238
239         //! Returns a constant handle to our object
240         handle<const value_type> constant()const { assert(obj); return *this; }
241
242         //! Returns number of instances
243         count_type
244         count()const
245                 { return obj?obj->count():0; }
246
247         //! Returns true if there is only one instance of the object
248         bool
249         unique()const
250                 { assert(obj); return count()==1; }
251
252         reference
253         operator*()const
254                 { assert(obj); return *obj; }
255
256         pointer
257         operator->()const
258                 { assert(obj); return obj; }
259
260         //! More explicit bool cast
261         operator bool()const
262                 { return obj!=NULL; }
263
264         operator handle<const value_type>()const
265         { return handle<const value_type>(static_cast<const_pointer>(obj)); }
266
267
268         //! <tt> static_cast\<\> </tt> wrapper
269         template <class U> static
270         handle<T> cast_static(const handle<U> &x)
271         { return handle<T>(static_cast<T*>(x.get())); }
272
273         //! <tt> dynamic_cast\<\> </tt> wrapper
274         template <class U> static
275         handle<T> cast_dynamic(const handle<U> &x)
276         { return handle<T>(dynamic_cast<T*>(x.get())); }
277
278         //! <tt> const_cast\<\> </tt> wrapper
279         template <class U> static
280         handle<T> cast_const(const handle<U> &x)
281         { return handle<T>(const_cast<T*>(x.get())); }
282
283         //! <tt> reinterpret_cast\<\> </tt> wrapper
284         template <class U> static
285         handle<T> cast_reinterpret(const handle<U> &x)
286         { return handle<T>(reinterpret_cast<T*>(x.get())); }
287
288         template<class U> static handle<T> cast_static(const loose_handle<U> &x);
289         template<class U> static handle<T> cast_dynamic(const loose_handle<U> &x);
290         template<class U> static handle<T> cast_const(const loose_handle<U> &x);
291         template<class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
292
293         template<class U> static handle<T> cast_static(const rhandle<U> &x);
294         template<class U> static handle<T> cast_dynamic(const rhandle<U> &x);
295         template<class U> static handle<T> cast_const(const rhandle<U> &x);
296         template<class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
297
298         template<class U> static handle<T> cast_static(U* x);
299         template<class U> static handle<T> cast_dynamic(U* x);
300         template<class U> static handle<T> cast_const(U* x);
301         template<class U> static handle<T> cast_reinterpret(U* x);
302
303         //! Returns pointer to the object that is being wrapped
304         pointer get()const { return obj; }
305
306         bool
307         operator!()const
308                 { return !obj; }
309
310         //! static_cast<> overload -- Useful for implicit casts
311         template <class U>
312         operator handle<U>()const
313         { return handle<U>(static_cast<U*>(obj)); }
314 }; // END of template class handle
315
316 // ========================================================================
317 /*!     \class  rshared_object _handle.h        ETL/handle
318 **      \brief  Replaceable Shared Object Base Class
319 **      \see rhandle
320 **      \writeme
321 */
322 class rshared_object : public shared_object
323 {
324 private:
325         mutable int rrefcount;
326
327 public:
328         void *front_;
329         void *back_;
330
331 protected:
332         rshared_object():rrefcount(0),front_(0),back_(0) { }
333
334 public:
335         void rref()const
336                 { rrefcount++; }
337
338         void runref()const
339         {
340                 assert(rrefcount>0);
341                 rrefcount--;
342         }
343
344         int rcount()const
345                 { return rrefcount; }
346 }; // END of class rshared_object
347
348 // ========================================================================
349 /*!     \class  rhandle _handle.h       ETL/handle
350 **      \brief  Replaceable Object Handle
351 **      \see rshared_object, handle, loose_handle
352 **      \writeme
353 */
354 template <class T>
355 class rhandle : public handle<T>
356 {
357         friend class rshared_object;
358 public:
359
360         typedef T value_type;
361         typedef T& reference;
362         typedef const T& const_reference;
363         typedef T* pointer;
364         typedef const T* const_pointer;
365         typedef int count_type;
366         typedef int size_type;
367
368
369         using handle<value_type>::count;
370         using handle<value_type>::unique;
371         using handle<value_type>::operator bool;
372         using handle<value_type>::get;
373         using handle<value_type>::operator *;
374         using handle<value_type>::operator ->;
375
376         /*
377         operator const handle<value_type>&()const
378         { return *this; }
379         */
380
381 private:
382         using handle<value_type>::obj;
383
384         rhandle<value_type> *prev_;
385         rhandle<value_type> *next_;
386
387         void add_to_rlist()
388         {
389 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
390
391                 assert(obj);
392                 obj->rref();
393
394                 // If this is the first reversible handle
395                 if(!obj->front_)
396                 {
397                         obj->front_=obj->back_=this;
398                         prev_=next_=0;
399                         return;
400                 }
401
402                 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
403                 next_=0;
404                 prev_->next_=this;
405                 obj->back_=this;
406         }
407
408         void del_from_rlist()
409         {
410 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
411                 assert(obj);
412                 obj->runref();
413
414                 // If this is the last reversible handle
415                 if(obj->front_==obj->back_)
416                 {
417                         obj->front_=obj->back_=0;
418                         prev_=next_=0;
419                         return;
420                 }
421
422                 if(!prev_)
423                         obj->front_=(void*)next_;
424                 else
425                         prev_->next_=next_;
426
427                 if(!next_)
428                         obj->back_=(void*)prev_;
429                 else
430                         next_->prev_=prev_;
431         }
432
433 public:
434
435         //! Default constructor - empty handle
436         rhandle() {}
437
438         //! Constructor that constructs from a pointer to new object
439         rhandle(pointer x):handle<T>(x)
440         {
441 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
442                 if(obj)add_to_rlist();
443         }
444
445         rhandle(const handle<value_type> &x):handle<T>(x)
446         {
447 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
448                 if(obj)add_to_rlist();
449         }
450
451         //! Default copy constructor
452         rhandle(const rhandle<value_type> &x):handle<T>(x)
453         {
454 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
455                 if(obj)add_to_rlist();
456         }
457
458         //! Handle is released on deletion
459         ~rhandle() { detach(); }
460
461         //! Template Assignment operator
462         /*! \note This class may not be necessary, and may be removed
463         **              at some point in the future.
464         */
465         /*
466         template <class U> const handle<value_type> &
467         operator=(const handle<U> &x)
468         {
469                 if(x.get()==obj)
470                         return *this;
471
472                 detach();
473
474                 obj=static_cast<value_type*>(x.get());
475                 if(obj)
476                 {
477                         obj->ref();
478                         add_to_rlist();
479                 }
480                 return *this;
481         }
482         */
483
484         //! Assignment operator
485         rhandle<value_type> &
486         operator=(const rhandle<value_type> &x)
487         {
488 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
489                 if(x.get()==obj)
490                         return *this;
491
492                 detach();
493
494                 obj=x.get();
495                 if(obj)
496                 {
497                         obj->ref();
498                         add_to_rlist();
499                 }
500                 return *this;
501         }
502
503         rhandle<value_type>&
504         operator=(const handle<value_type> &x)
505         {
506 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
507                 if(x.get()==obj)
508                         return *this;
509
510                 detach();
511
512                 obj=x.get();
513                 if(obj)
514                 {
515                         obj->ref();
516                         add_to_rlist();
517                 }
518                 return *this;
519         }
520
521         rhandle<value_type>&
522         operator=(value_type* x)
523         {
524 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
525                 if(x==obj)
526                         return *this;
527
528                 detach();
529
530                 obj=x;
531                 if(obj)
532                 {
533                         obj->ref();
534                         add_to_rlist();
535                 }
536                 return *this;
537         }
538
539         //! Handle release procedure
540         /*! unref()'s the object and sets the internal object pointer to \c NULL */
541         void
542         detach()
543         {
544 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
545                 if(obj)del_from_rlist();
546                 handle<value_type>::detach();
547                 obj=0;
548         }
549
550         // This will be reintroduced with a new function
551         //void release() { detach(); }
552
553         void reset() { detach(); }
554
555         //! Creates a new instance of a T object and puts it in the handle.
556         /*! Uses the default constructor */
557         void spawn() { operator=(handle<value_type>(new T())); }
558
559         //! Returns number of reversible instances
560         count_type
561         rcount()const
562         {
563 //              value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
564                 return obj?obj->rcount():0;
565         }
566
567         //! Returns true if there is only one instance of the object
568         bool
569         runique()const
570         {
571 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
572                 assert(obj); return obj->front_==obj->back_;
573         }
574
575         //! \writeme
576         int replace(const handle<value_type> &x)
577         {
578 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
579                 assert(obj);
580                 assert(x.get()!=obj);
581
582                 if(x.get()==obj)
583                         return 0;
584
585                 rhandle<value_type> *iter;
586                 rhandle<value_type> *next;
587
588                 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
589
590                 assert(iter);
591
592                 next=iter->next_;
593
594                 int i=0;
595                 #ifndef NDEBUG
596                 pointer obj_=obj;
597                 #endif
598
599                 for(;iter;iter=next,next=iter?iter->next_:0,i++)
600                 {
601                         assert(iter->get()==obj_);
602                         (*iter)=x;
603                 }
604
605                 assert(obj==x.get());
606
607                 return i;
608         }
609
610         //! Swaps the values of two handles without reference counts
611         /*!     \warning not yet implemented. \writeme */
612         handle<value_type> &
613         swap(handle<value_type> &x);
614         /*
615         {
616                 assert(0);
617                 pointer ptr=x.obj;
618                 x.obj=x.get();
619                 obj=ptr;
620                 return *this;
621         }
622         */
623 }; // END of template class rhandle
624
625
626
627
628
629
630
631 // ========================================================================
632 /*!     \class  loose_handle _handle.h  ETL/handle
633 **      \brief  Loose Object Handle
634 **      \see shared_object, handle
635 **      \writeme
636 */
637 template <class T>
638 class loose_handle
639 {
640 public:
641
642         typedef T value_type;
643         typedef T& reference;
644         typedef const T& const_reference;
645         typedef T* pointer;
646         typedef const T* const_pointer;
647         typedef int count_type;
648         typedef int size_type;
649
650 protected:
651         value_type *obj;                //!< Pointer to object
652
653 public:
654
655         //! Default constructor - empty handle
656         loose_handle():obj(0) {}
657
658         //! Constructor that constructs from a pointer to new object
659         loose_handle(pointer x):obj(x) { }
660
661         //! Default copy constructor
662         loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
663
664         loose_handle(const handle<value_type> &x):obj(x.get()) { }
665
666         template <class U> const loose_handle<value_type> &
667         operator=(const handle<U> &x)
668         {
669                 if(x.get()==obj)
670                         return *this;
671
672                 obj=static_cast<value_type*>(x.get());
673                 return *this;
674         }
675
676         template <class U> const loose_handle<value_type> &
677         operator=(const loose_handle<U> &x)
678         {
679                 if(x.get()==obj)
680                         return *this;
681
682                 obj=static_cast<value_type*>(x.get());
683                 return *this;
684         }
685
686         //! Assignment operator
687         const loose_handle<value_type> &
688         operator=(const loose_handle<value_type> &x)
689         {
690                 if(x.get()==obj)
691                         return *this;
692
693                 obj=x.get();
694                 return *this;
695         }
696
697         //! Swaps the values of two handles without reference counts
698         loose_handle<value_type> &
699         swap(loose_handle<value_type> &x)
700         {
701                 pointer ptr=x.obj;
702                 x.obj=x.get();
703                 obj=ptr;
704                 return *this;
705         }
706
707         //! Handle release procedure
708         void detach() { obj=0;  }
709
710         // This will be reintroduced with a new function
711         //void release() { detach(); }
712
713         void reset() { detach(); }
714
715         bool empty()const { return obj==0; }
716
717         handle<value_type> clone()const { assert(obj); return obj->clone(); }
718
719         //! Returns a constant handle to our object
720         loose_handle<const value_type> constant()const { return *this; }
721
722         //! Returns number of instances
723         count_type
724         count()const
725                 { return obj?obj->count():0; }
726
727         reference
728         operator*()const
729                 { assert(obj); return *obj; }
730
731         pointer
732         operator->()const
733                 { assert(obj); return obj; }
734
735         //! static_cast<> overload
736         //template <class U>
737         //operator loose_handle<U>()const
738         //{ return loose_handle<U>(static_cast<U*>(obj)); }
739
740         //! static_cast<> overload (for consts)
741         operator loose_handle<const value_type>()const
742         { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
743
744         operator handle<value_type>()const
745         { return handle<value_type>(obj); }
746
747         operator rhandle<value_type>()const
748         { return rhandle<value_type>(obj); }
749
750         //! Returns pointer to the object that is being wrapped
751         pointer get()const { return obj; }
752
753         //! More explicit bool cast
754         operator bool()const
755                 { return obj!=0; }
756
757         bool
758         operator!()const
759                 { return !obj; }
760
761         void ref() { if(obj)obj->ref(); }
762
763         bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
764 }; // END of template class loose_handle
765
766
767
768
769 template<class T> template<class U> handle<T>
770 handle<T>::cast_static(const loose_handle<U> &x)
771         { return handle<T>(static_cast<T*>(x.get())); }
772
773 template <class T> template <class U> handle<T>
774 handle<T>::cast_dynamic(const loose_handle<U> &x)
775         { return handle<T>(dynamic_cast<T*>(x.get())); }
776
777 template <class T> template <class U> handle<T>
778 handle<T>::cast_const(const loose_handle<U> &x)
779         { return handle<T>(const_cast<T*>(x.get())); }
780
781 template <class T> template <class U> handle<T>
782 handle<T>::cast_reinterpret(const loose_handle<U> &x)
783         { return handle<T>(reinterpret_cast<T*>(x.get())); }
784
785
786
787 template <class T> template <class U> handle<T>
788 handle<T>::cast_static(const rhandle<U> &x)
789         { return handle<T>(static_cast<T*>(x.get())); }
790
791 template <class T> template <class U> handle<T>
792 handle<T>::cast_dynamic(const rhandle<U> &x)
793         { return handle<T>(dynamic_cast<T*>(x.get())); }
794
795 template <class T> template <class U> handle<T>
796 handle<T>::cast_const(const rhandle<U> &x)
797         { return handle<T>(const_cast<T*>(x.get())); }
798
799 template <class T> template <class U> handle<T>
800 handle<T>::cast_reinterpret(const rhandle<U> &x)
801         { return handle<T>(reinterpret_cast<T*>(x.get())); }
802
803
804
805 template <class T> template <class U> handle<T>
806 handle<T>::cast_static(U* x)
807         { return handle<T>(static_cast<T*>(x)); }
808
809 template <class T> template <class U> handle<T>
810 handle<T>::cast_dynamic(U* x)
811         { return handle<T>(dynamic_cast<T*>(x)); }
812
813 template <class T> template <class U> handle<T>
814 handle<T>::cast_const(U* x)
815         { return handle<T>(const_cast<T*>(x)); }
816
817 template <class T> template <class U> handle<T>
818 handle<T>::cast_reinterpret(U* x)
819         { return handle<T>(reinterpret_cast<T*>(x)); }
820
821
822
823
824
825 template <class T,class U> bool
826 operator==(const handle<T> &lhs,const handle<U> &rhs)
827         { return (lhs.get()==rhs.get()); }
828 template <class T,class U> bool
829 operator==(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
830         { return (lhs.get()==rhs.get()); }
831 template <class T,class U> bool
832 operator==(const handle<T> &lhs,const loose_handle<U> &rhs)
833         { return (lhs.get()==rhs.get()); }
834 template <class T,class U> bool
835 operator==(const loose_handle<T> &lhs,const handle<U> &rhs)
836         { return (lhs.get()==rhs.get()); }
837 template <class T> bool
838 operator==(const handle<T> &lhs,const T *rhs)
839         { return (lhs.get()==rhs); }
840 template <class T> bool
841 operator==(const loose_handle<T> &lhs,const T *rhs)
842         { return (lhs.get()==rhs); }
843 template <class T> bool
844 operator==(const T *lhs,const handle<T> &rhs)
845         { return (lhs==rhs.get()); }
846 template <class T> bool
847 operator==(const T *lhs,const loose_handle<T> &rhs)
848         { return (lhs==rhs.get()); }
849
850
851 template <class T,class U> bool
852 operator!=(const handle<T> &lhs,const handle<U> &rhs)
853         { return (lhs.get()!=rhs.get()); }
854 template <class T,class U> bool
855 operator!=(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
856         { return (lhs.get()!=rhs.get()); }
857 template <class T,class U> bool
858 operator!=(const handle<T> &lhs,const loose_handle<U> &rhs)
859         { return (lhs.get()!=rhs.get()); }
860 template <class T,class U> bool
861 operator!=(const loose_handle<T> &lhs,const handle<U> &rhs)
862         { return (lhs.get()!=rhs.get()); }
863 template <class T> bool
864 operator!=(const handle<T> &lhs,const T *rhs)
865         { return (lhs.get()!=rhs); }
866 template <class T> bool
867 operator!=(const loose_handle<T> &lhs,const T *rhs)
868         { return (lhs.get()!=rhs); }
869 template <class T> bool
870 operator!=(const T *lhs,const handle<T> &rhs)
871         { return (lhs!=rhs.get()); }
872 template <class T> bool
873 operator!=(const T *lhs,const loose_handle<T> &rhs)
874         { return (lhs!=rhs.get()); }
875
876
877 template <class T,class U> bool
878 operator<(const handle<T> &lhs,const handle<U> &rhs)
879         { return (lhs.get()<rhs.get()); }
880 template <class T,class U> bool
881 operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
882         { return (lhs.get()<rhs.get()); }
883 template <class T,class U> bool
884 operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
885         { return (lhs.get()<rhs.get()); }
886 template <class T,class U> bool
887 operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
888         { return (lhs.get()<rhs.get()); }
889 template <class T> bool
890 operator<(const handle<T> &lhs,const T *rhs)
891         { return (lhs.get()<rhs); }
892 template <class T> bool
893 operator<(const loose_handle<T> &lhs,const T *rhs)
894         { return (lhs.get()<rhs); }
895 template <class T> bool
896 operator<(const T *lhs,const handle<T> &rhs)
897         { return (lhs<rhs.get()); }
898 template <class T> bool
899 operator<(const T *lhs,const loose_handle<T> &rhs)
900         { return (lhs<rhs.get()); }
901
902 _ETL_END_NAMESPACE
903
904 /* === E N D =============================================================== */
905
906 #endif