Initial import of ETL
[synfig.git] / ETL / trunk / ETL / _handle.h
1 /* === E T L =============================================================== */
2 /*!     \file _handle.h
3 **      $Id: _handle.h,v 1.1.1.1 2005/01/04 01:31:47 darco Exp $
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         //! static_cast<> overload -- Useful for implicit casts
261         template <class U>
262         operator handle<U>()const
263         { return handle<U>(static_cast<U*>(obj)); }
264
265         operator handle<const value_type>()const
266         { return handle<const value_type>(static_cast<const_pointer>(obj)); }
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         //! More explicit bool cast
307         operator bool()const
308                 { return obj!=NULL; }
309
310         bool
311         operator!()const
312                 { return !obj; }
313 }; // END of template class handle
314
315 // ========================================================================
316 /*!     \class  rshared_object _handle.h        ETL/handle
317 **      \brief  Replaceable Shared Object Base Class
318 **      \see rhandle
319 **      \writeme
320 */
321 class rshared_object : public shared_object
322 {
323 private:
324         mutable int rrefcount;
325
326 public:
327         void *front_;
328         void *back_;
329         
330 protected:
331         rshared_object():rrefcount(0),front_(0),back_(0) { }
332         
333 public: 
334         void rref()const
335                 { rrefcount++; }
336         
337         void runref()const
338         {
339                 assert(rrefcount>0);
340                 rrefcount--;
341         }
342         
343         int rcount()const
344                 { return rrefcount; }
345 }; // END of class rshared_object
346
347 // ========================================================================
348 /*!     \class  rhandle _handle.h       ETL/handle
349 **      \brief  Replaceable Object Handle
350 **      \see rshared_object, handle, loose_handle
351 **      \writeme
352 */
353 template <class T>
354 class rhandle : public handle<T>
355 {
356         friend class rshared_object;
357 public:
358
359         typedef T value_type;
360         typedef T& reference;
361         typedef const T& const_reference;
362         typedef T* pointer;
363         typedef const T* const_pointer;
364         typedef int count_type;
365         typedef int size_type;
366
367
368         using handle<value_type>::count;
369         using handle<value_type>::unique;
370         using handle<value_type>::operator bool;
371         using handle<value_type>::get;
372         using handle<value_type>::operator *;
373         using handle<value_type>::operator ->;
374         
375         /*
376         operator const handle<value_type>&()const
377         { return *this; }
378         */
379
380 private:
381         using handle<value_type>::obj;
382         
383         rhandle<value_type> *prev_;
384         rhandle<value_type> *next_;
385
386         void add_to_rlist()
387         {
388 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
389
390                 assert(obj);
391                 obj->rref();
392
393                 // If this is the first reversable handle
394                 if(!obj->front_)
395                 {
396                         obj->front_=obj->back_=this;
397                         prev_=next_=0;
398                         return;
399                 }
400                 
401                 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
402                 next_=0;
403                 prev_->next_=this;
404                 obj->back_=this;
405         }
406
407         void del_from_rlist()
408         {
409 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
410                 assert(obj);
411                 obj->runref();
412
413                 // If this is the last reversable handle
414                 if(obj->front_==obj->back_)
415                 {
416                         obj->front_=obj->back_=0;
417                         prev_=next_=0;
418                         return;
419                 }
420
421                 if(!prev_)
422                         obj->front_=(void*)next_;
423                 else
424                         prev_->next_=next_;
425
426                 if(!next_)
427                         obj->back_=(void*)prev_;
428                 else
429                         next_->prev_=prev_;
430         }
431         
432 public:
433
434         //! Default constructor - empty handle
435         rhandle() {}
436
437         //! Constructor that constructs from a pointer to new object
438         rhandle(pointer x):handle<T>(x)
439         {
440 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
441                 if(obj)add_to_rlist();
442         }
443
444         rhandle(const handle<value_type> &x):handle<T>(x)
445         {
446 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
447                 if(obj)add_to_rlist();
448         }
449
450         //! Default copy constructor
451         rhandle(const rhandle<value_type> &x):handle<T>(x)
452         {
453 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
454                 if(obj)add_to_rlist();
455         }
456
457         //! Handle is released on deletion
458         ~rhandle() { detach(); }
459                 
460         //! Template Assignment operator
461         /*! \note This class may not be necessary, and may be removed
462         **              at some point in the future.
463         */
464         /*
465         template <class U> const handle<value_type> &
466         operator=(const handle<U> &x)
467         {
468                 if(x.get()==obj)
469                         return *this;
470
471                 detach();
472
473                 obj=static_cast<value_type*>(x.get());
474                 if(obj)
475                 {
476                         obj->ref();
477                         add_to_rlist();
478                 }
479                 return *this;
480         }
481         */
482         
483         //! Assignment operator
484         rhandle<value_type> &
485         operator=(const rhandle<value_type> &x)
486         {
487 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
488                 if(x.get()==obj)
489                         return *this;
490
491                 detach();
492
493                 obj=x.get();
494                 if(obj)
495                 {
496                         obj->ref();
497                         add_to_rlist();
498                 }
499                 return *this;
500         }
501
502         rhandle<value_type>&
503         operator=(const handle<value_type> &x)
504         {
505 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
506                 if(x.get()==obj)
507                         return *this;
508
509                 detach();
510
511                 obj=x.get();
512                 if(obj)
513                 {
514                         obj->ref();
515                         add_to_rlist();
516                 }
517                 return *this;
518         }
519
520         rhandle<value_type>&
521         operator=(value_type* x)
522         {
523 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
524                 if(x==obj)
525                         return *this;
526
527                 detach();
528
529                 obj=x;
530                 if(obj)
531                 {
532                         obj->ref();
533                         add_to_rlist();
534                 }
535                 return *this;
536         }
537
538         //! Handle release procedure
539         /*! unref()'s the object and sets the internal object pointer to \c NULL */
540         void
541         detach()
542         {
543 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
544                 if(obj)del_from_rlist();
545                 handle<value_type>::detach();
546                 obj=0;
547         }
548
549         // This will be reintroduced with a new function
550         //void release() { detach(); }
551
552         void reset() { detach(); }
553
554         //! Creates a new instance of a T object and puts it in the handle.
555         /*! Uses the default constructor */
556         void spawn() { operator=(handle<value_type>(new T())); }
557
558         //! Returns number of reversable instances
559         count_type
560         rcount()const
561         {
562 //              value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
563                 return obj?obj->rcount():0;
564         }
565
566         //! Returns true if there is only one instance of the object
567         bool
568         runique()const
569         {
570 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
571                 assert(obj); return obj->front_==obj->back_;
572         }
573
574         //! \writeme
575         int replace(const handle<value_type> &x)
576         {
577 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
578                 assert(obj);
579                 assert(x.get()!=obj);
580                 
581                 if(x.get()==obj)
582                         return 0;
583                 
584                 rhandle<value_type> *iter;
585                 rhandle<value_type> *next;
586                 
587                 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
588
589                 assert(iter);           
590
591                 next=iter->next_;
592                 
593                 int i=0;
594                 #ifndef NDEBUG
595                 pointer obj_=obj;
596                 #endif
597                 
598                 for(;iter;iter=next,next=iter?iter->next_:0,i++)
599                 {
600                         assert(iter->get()==obj_);      
601                         (*iter)=x;
602                 }
603
604                 assert(obj==x.get());
605                 
606                 return i;
607         }
608
609         //! Swaps the values of two handles without reference counts
610         /*!     \warning not yet implemented. \writeme */
611         handle<value_type> &
612         swap(handle<value_type> &x);
613         /*
614         {
615                 assert(0);
616                 pointer ptr=x.obj;
617                 x.obj=x.get();
618                 obj=ptr;
619                 return *this;
620         }
621         */
622 }; // END of template class rhandle
623
624
625
626
627
628
629
630 // ========================================================================
631 /*!     \class  loose_handle _handle.h  ETL/handle
632 **      \brief  Loose Object Handle
633 **      \see shared_object, handle
634 **      \writeme
635 */
636 template <class T>
637 class loose_handle
638 {
639 public:
640
641         typedef T value_type;
642         typedef T& reference;
643         typedef const T& const_reference;
644         typedef T* pointer;
645         typedef const T* const_pointer;
646         typedef int count_type;
647         typedef int size_type;
648
649 protected:
650         value_type *obj;                //!< Pointer to object
651
652 public:
653
654         //! Default constructor - empty handle
655         loose_handle():obj(0) {}
656
657         //! Constructor that constructs from a pointer to new object
658         loose_handle(pointer x):obj(x) { }
659
660         //! Default copy constructor
661         loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
662
663         loose_handle(const handle<value_type> &x):obj(x.get()) { }
664
665         template <class U> const loose_handle<value_type> &
666         operator=(const handle<U> &x)
667         {
668                 if(x.get()==obj)
669                         return *this;
670
671                 obj=static_cast<value_type*>(x.get());
672                 return *this;
673         }
674
675         template <class U> const loose_handle<value_type> &
676         operator=(const loose_handle<U> &x)
677         {
678                 if(x.get()==obj)
679                         return *this;
680
681                 obj=static_cast<value_type*>(x.get());
682                 return *this;
683         }
684
685         //! Assignment operator
686         const loose_handle<value_type> &
687         operator=(const loose_handle<value_type> &x)
688         {
689                 if(x.get()==obj)
690                         return *this;
691
692                 obj=x.get();
693                 return *this;
694         }
695
696         //! Swaps the values of two handles without reference counts
697         loose_handle<value_type> &
698         swap(loose_handle<value_type> &x)
699         {
700                 pointer ptr=x.obj;
701                 x.obj=x.get();
702                 obj=ptr;
703                 return *this;
704         }
705
706         //! Handle release procedure
707         void detach() { obj=0;  }
708
709         // This will be reintroduced with a new function
710         //void release() { detach(); }
711
712         void reset() { detach(); }
713         
714         bool empty()const { return obj==0; }
715
716         handle<value_type> clone()const { assert(obj); return obj->clone(); }
717
718         //! Returns a constant handle to our object
719         loose_handle<const value_type> constant()const { return *this; }
720
721         //! Returns number of instances
722         count_type
723         count()const
724                 { return obj?obj->count():0; }
725
726         reference
727         operator*()const
728                 { assert(obj); return *obj; }
729
730         pointer
731         operator->()const
732                 { assert(obj); return obj; }
733
734         //! static_cast<> overload
735         //template <class U>
736         //operator loose_handle<U>()const
737         //{ return loose_handle<U>(static_cast<U*>(obj)); }
738
739         //! static_cast<> overload (for consts)
740         operator loose_handle<const value_type>()const
741         { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
742
743         operator handle<value_type>()const
744         { return handle<value_type>(obj); }
745
746         operator rhandle<value_type>()const
747         { return rhandle<value_type>(obj); }
748
749         //! Returns pointer to the object that is being wrapped
750         pointer get()const { return obj; }
751
752         //! More explicit bool cast
753         operator bool()const
754                 { return obj!=0; }
755
756         bool
757         operator!()const
758                 { return !obj; }
759
760         void ref() { if(obj)obj->ref(); }
761
762         bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
763 }; // END of template class loose_handle
764
765
766
767
768 template<class T> template<class U> handle<T>
769 handle<T>::cast_static(const loose_handle<U> &x)
770         { return handle<T>(static_cast<T*>(x.get())); }
771
772 template <class T> template <class U> handle<T>
773 handle<T>::cast_dynamic(const loose_handle<U> &x)
774         { return handle<T>(dynamic_cast<T*>(x.get())); }
775
776 template <class T> template <class U> handle<T>
777 handle<T>::cast_const(const loose_handle<U> &x)
778         { return handle<T>(const_cast<T*>(x.get())); }
779
780 template <class T> template <class U> handle<T>
781 handle<T>::cast_reinterpret(const loose_handle<U> &x)
782         { return handle<T>(reinterpret_cast<T*>(x.get())); }
783
784         
785         
786 template <class T> template <class U> handle<T>
787 handle<T>::cast_static(const rhandle<U> &x)
788         { return handle<T>(static_cast<T*>(x.get())); }
789
790 template <class T> template <class U> handle<T>
791 handle<T>::cast_dynamic(const rhandle<U> &x)
792         { return handle<T>(dynamic_cast<T*>(x.get())); }
793
794 template <class T> template <class U> handle<T>
795 handle<T>::cast_const(const rhandle<U> &x)
796         { return handle<T>(const_cast<T*>(x.get())); }
797
798 template <class T> template <class U> handle<T>
799 handle<T>::cast_reinterpret(const rhandle<U> &x)
800         { return handle<T>(reinterpret_cast<T*>(x.get())); }
801
802         
803         
804 template <class T> template <class U> handle<T>
805 handle<T>::cast_static(U* x)
806         { return handle<T>(static_cast<T*>(x)); }
807
808 template <class T> template <class U> handle<T>
809 handle<T>::cast_dynamic(U* x)
810         { return handle<T>(dynamic_cast<T*>(x)); }
811
812 template <class T> template <class U> handle<T>
813 handle<T>::cast_const(U* x)
814         { return handle<T>(const_cast<T*>(x)); }
815
816 template <class T> template <class U> handle<T>
817 handle<T>::cast_reinterpret(U* x)
818         { return handle<T>(reinterpret_cast<T*>(x)); }
819
820
821
822
823
824 template <class T,class U> bool
825 operator==(const handle<T> &lhs,const handle<U> &rhs)
826         { return (lhs.get()==rhs.get()); }
827 template <class T,class U> bool
828 operator==(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
829         { return (lhs.get()==rhs.get()); }
830 template <class T,class U> bool
831 operator==(const handle<T> &lhs,const loose_handle<U> &rhs)
832         { return (lhs.get()==rhs.get()); }
833 template <class T,class U> bool
834 operator==(const loose_handle<T> &lhs,const handle<U> &rhs)
835         { return (lhs.get()==rhs.get()); }
836 template <class T> bool
837 operator==(const handle<T> &lhs,const T *rhs)
838         { return (lhs.get()==rhs); }
839 template <class T> bool
840 operator==(const loose_handle<T> &lhs,const T *rhs)
841         { return (lhs.get()==rhs); }
842 template <class T> bool
843 operator==(const T *lhs,const handle<T> &rhs)
844         { return (lhs==rhs.get()); }
845 template <class T> bool
846 operator==(const T *lhs,const loose_handle<T> &rhs)
847         { return (lhs==rhs.get()); }
848
849
850 template <class T,class U> bool
851 operator!=(const handle<T> &lhs,const handle<U> &rhs)
852         { return (lhs.get()!=rhs.get()); }
853 template <class T,class U> bool
854 operator!=(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
855         { return (lhs.get()!=rhs.get()); }
856 template <class T,class U> bool
857 operator!=(const handle<T> &lhs,const loose_handle<U> &rhs)
858         { return (lhs.get()!=rhs.get()); }
859 template <class T,class U> bool
860 operator!=(const loose_handle<T> &lhs,const handle<U> &rhs)
861         { return (lhs.get()!=rhs.get()); }
862 template <class T> bool
863 operator!=(const handle<T> &lhs,const T *rhs)
864         { return (lhs.get()!=rhs); }
865 template <class T> bool
866 operator!=(const loose_handle<T> &lhs,const T *rhs)
867         { return (lhs.get()!=rhs); }
868 template <class T> bool
869 operator!=(const T *lhs,const handle<T> &rhs)
870         { return (lhs!=rhs.get()); }
871 template <class T> bool
872 operator!=(const T *lhs,const loose_handle<T> &rhs)
873         { return (lhs!=rhs.get()); }
874
875
876 template <class T,class U> bool
877 operator<(const handle<T> &lhs,const handle<U> &rhs)
878         { return (lhs.get()<rhs.get()); }
879 template <class T,class U> bool
880 operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
881         { return (lhs.get()<rhs.get()); }
882 template <class T,class U> bool
883 operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
884         { return (lhs.get()<rhs.get()); }
885 template <class T,class U> bool
886 operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
887         { return (lhs.get()<rhs.get()); }
888 template <class T> bool
889 operator<(const handle<T> &lhs,const T *rhs)
890         { return (lhs.get()<rhs); }
891 template <class T> bool
892 operator<(const loose_handle<T> &lhs,const T *rhs)
893         { return (lhs.get()<rhs); }
894 template <class T> bool
895 operator<(const T *lhs,const handle<T> &rhs)
896         { return (lhs<rhs.get()); }
897 template <class T> bool
898 operator<(const T *lhs,const loose_handle<T> &rhs)
899         { return (lhs<rhs.get()); }
900
901 _ETL_END_NAMESPACE
902
903 /* === E N D =============================================================== */
904
905 #endif