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