Tidying.
[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 **
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         //! <tt> static_cast\<\> </tt> wrapper
268         template <class U> static handle<T> cast_static         (const handle<U> &x) { return handle<T>(static_cast             <T*>(x.get())); }
269         //! <tt> dynamic_cast\<\> </tt> wrapper
270         template <class U> static handle<T> cast_dynamic        (const handle<U> &x) { return handle<T>(dynamic_cast    <T*>(x.get())); }
271         //! <tt> const_cast\<\> </tt> wrapper
272         template <class U> static handle<T> cast_const          (const handle<U> &x) { return handle<T>(const_cast              <T*>(x.get())); }
273         //! <tt> reinterpret_cast\<\> </tt> wrapper
274         template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
275
276         template <class U> static handle<T> cast_static         (const loose_handle<U> &x);
277         template <class U> static handle<T> cast_dynamic        (const loose_handle<U> &x);
278         template <class U> static handle<T> cast_const          (const loose_handle<U> &x);
279         template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
280
281         template <class U> static handle<T> cast_static         (const rhandle<U> &x);
282         template <class U> static handle<T> cast_dynamic        (const rhandle<U> &x);
283         template <class U> static handle<T> cast_const          (const rhandle<U> &x);
284         template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
285
286         template <class U> static handle<T> cast_static         (U* x);
287         template <class U> static handle<T> cast_dynamic        (U* x);
288         template <class U> static handle<T> cast_const          (U* x);
289         template <class U> static handle<T> cast_reinterpret(U* x);
290
291         //! Returns pointer to the object that is being wrapped
292         pointer get()const { return obj; }
293
294         bool
295         operator!()const
296                 { return !obj; }
297
298         //! static_cast<> overload -- Useful for implicit casts
299         template <class U>
300         operator handle<U>()const
301         { return handle<U>(static_cast<U*>(obj)); }
302 }; // END of template class handle
303
304 // ========================================================================
305 /*!     \class  rshared_object _handle.h        ETL/handle
306 **      \brief  Replaceable Shared Object Base Class
307 **      \see rhandle
308 **      \writeme
309 */
310 class rshared_object : public shared_object
311 {
312 private:
313         mutable int rrefcount;
314
315 public:
316         void *front_;
317         void *back_;
318
319 protected:
320         rshared_object():rrefcount(0),front_(0),back_(0) { }
321
322 public:
323         void rref()const
324                 { rrefcount++; }
325
326         void runref()const
327         {
328                 assert(rrefcount>0);
329                 rrefcount--;
330         }
331
332         int rcount()const
333                 { return rrefcount; }
334 }; // END of class rshared_object
335
336 // ========================================================================
337 /*!     \class  rhandle _handle.h       ETL/handle
338 **      \brief  Replaceable Object Handle
339 **      \see rshared_object, handle, loose_handle
340 **      \writeme
341 */
342 template <class T>
343 class rhandle : public handle<T>
344 {
345         friend class rshared_object;
346 public:
347
348         typedef T value_type;
349         typedef T& reference;
350         typedef const T& const_reference;
351         typedef T* pointer;
352         typedef const T* const_pointer;
353         typedef int count_type;
354         typedef int size_type;
355
356
357         using handle<value_type>::count;
358         using handle<value_type>::unique;
359         using handle<value_type>::operator bool;
360         using handle<value_type>::get;
361         using handle<value_type>::operator *;
362         using handle<value_type>::operator ->;
363
364         /*
365         operator const handle<value_type>&()const
366         { return *this; }
367         */
368
369 private:
370         using handle<value_type>::obj;
371
372         rhandle<value_type> *prev_;
373         rhandle<value_type> *next_;
374
375         void add_to_rlist()
376         {
377 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
378
379                 assert(obj);
380                 obj->rref();
381
382                 // If this is the first reversible handle
383                 if(!obj->front_)
384                 {
385                         obj->front_=obj->back_=this;
386                         prev_=next_=0;
387                         return;
388                 }
389
390                 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
391                 next_=0;
392                 prev_->next_=this;
393                 obj->back_=this;
394         }
395
396         void del_from_rlist()
397         {
398 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
399                 assert(obj);
400                 obj->runref();
401
402                 // If this is the last reversible handle
403                 if(obj->front_==obj->back_)
404                 {
405                         obj->front_=obj->back_=0;
406                         prev_=next_=0;
407                         return;
408                 }
409
410                 if(!prev_)
411                         obj->front_=(void*)next_;
412                 else
413                         prev_->next_=next_;
414
415                 if(!next_)
416                         obj->back_=(void*)prev_;
417                 else
418                         next_->prev_=prev_;
419         }
420
421 public:
422
423         //! Default constructor - empty handle
424         rhandle() {}
425
426         //! Constructor that constructs from a pointer to new object
427         rhandle(pointer x):handle<T>(x)
428         {
429 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
430                 if(obj)add_to_rlist();
431         }
432
433         rhandle(const handle<value_type> &x):handle<T>(x)
434         {
435 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
436                 if(obj)add_to_rlist();
437         }
438
439         //! Default copy constructor
440         rhandle(const rhandle<value_type> &x):handle<T>(x)
441         {
442 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
443                 if(obj)add_to_rlist();
444         }
445
446         //! Handle is released on deletion
447         ~rhandle() { detach(); }
448
449         //! Template Assignment operator
450         /*! \note This class may not be necessary, and may be removed
451         **              at some point in the future.
452         */
453         /*
454         template <class U> const handle<value_type> &
455         operator=(const handle<U> &x)
456         {
457                 if(x.get()==obj)
458                         return *this;
459
460                 detach();
461
462                 obj=static_cast<value_type*>(x.get());
463                 if(obj)
464                 {
465                         obj->ref();
466                         add_to_rlist();
467                 }
468                 return *this;
469         }
470         */
471
472         //! Assignment operator
473         rhandle<value_type> &
474         operator=(const rhandle<value_type> &x)
475         {
476 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
477                 if(x.get()==obj)
478                         return *this;
479
480                 detach();
481
482                 obj=x.get();
483                 if(obj)
484                 {
485                         obj->ref();
486                         add_to_rlist();
487                 }
488                 return *this;
489         }
490
491         rhandle<value_type>&
492         operator=(const handle<value_type> &x)
493         {
494 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
495                 if(x.get()==obj)
496                         return *this;
497
498                 detach();
499
500                 obj=x.get();
501                 if(obj)
502                 {
503                         obj->ref();
504                         add_to_rlist();
505                 }
506                 return *this;
507         }
508
509         rhandle<value_type>&
510         operator=(value_type* x)
511         {
512 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
513                 if(x==obj)
514                         return *this;
515
516                 detach();
517
518                 obj=x;
519                 if(obj)
520                 {
521                         obj->ref();
522                         add_to_rlist();
523                 }
524                 return *this;
525         }
526
527         //! Handle release procedure
528         /*! unref()'s the object and sets the internal object pointer to \c NULL */
529         void
530         detach()
531         {
532 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
533                 if(obj)del_from_rlist();
534                 handle<value_type>::detach();
535                 obj=0;
536         }
537
538         // This will be reintroduced with a new function
539         //void release() { detach(); }
540
541         void reset() { detach(); }
542
543         //! Creates a new instance of a T object and puts it in the handle.
544         /*! Uses the default constructor */
545         void spawn() { operator=(handle<value_type>(new T())); }
546
547         //! Returns number of reversible instances
548         count_type
549         rcount()const
550         {
551 //              value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
552                 return obj?obj->rcount():0;
553         }
554
555         //! Returns true if there is only one instance of the object
556         bool
557         runique()const
558         {
559 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
560                 assert(obj); return obj->front_==obj->back_;
561         }
562
563         //! \writeme
564         int replace(const handle<value_type> &x)
565         {
566 //              value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
567                 assert(obj);
568                 assert(x.get()!=obj);
569
570                 if(x.get()==obj)
571                         return 0;
572
573                 rhandle<value_type> *iter;
574                 rhandle<value_type> *next;
575
576                 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
577
578                 assert(iter);
579
580                 next=iter->next_;
581
582                 int i=0;
583                 #ifndef NDEBUG
584                 pointer obj_=obj;
585                 #endif
586
587                 for(;iter;iter=next,next=iter?iter->next_:0,i++)
588                 {
589                         assert(iter->get()==obj_);
590                         (*iter)=x;
591                 }
592
593                 assert(obj==x.get());
594
595                 return i;
596         }
597
598         //! Swaps the values of two handles without reference counts
599         /*!     \warning not yet implemented. \writeme */
600         handle<value_type> &
601         swap(handle<value_type> &x);
602         /*
603         {
604                 assert(0);
605                 pointer ptr=x.obj;
606                 x.obj=x.get();
607                 obj=ptr;
608                 return *this;
609         }
610         */
611 }; // END of template class rhandle
612
613
614 // ========================================================================
615 /*!     \class  loose_handle _handle.h  ETL/handle
616 **      \brief  Loose Object Handle
617 **      \see shared_object, handle
618 **      \writeme
619 */
620 template <class T>
621 class loose_handle
622 {
623 public:
624
625         typedef T value_type;
626         typedef T& reference;
627         typedef const T& const_reference;
628         typedef T* pointer;
629         typedef const T* const_pointer;
630         typedef int count_type;
631         typedef int size_type;
632
633 protected:
634         value_type *obj;                //!< Pointer to object
635
636 public:
637
638         //! Default constructor - empty handle
639         loose_handle():obj(0) {}
640
641         //! Constructor that constructs from a pointer to new object
642         loose_handle(pointer x):obj(x) { }
643
644         //! Default copy constructor
645         loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
646
647         loose_handle(const handle<value_type> &x):obj(x.get()) { }
648
649         template <class U> const loose_handle<value_type> &
650         operator=(const handle<U> &x)
651         {
652                 if(x.get()==obj)
653                         return *this;
654
655                 obj=static_cast<value_type*>(x.get());
656                 return *this;
657         }
658
659         template <class U> const loose_handle<value_type> &
660         operator=(const loose_handle<U> &x)
661         {
662                 if(x.get()==obj)
663                         return *this;
664
665                 obj=static_cast<value_type*>(x.get());
666                 return *this;
667         }
668
669         //! Assignment operator
670         const loose_handle<value_type> &
671         operator=(const loose_handle<value_type> &x)
672         {
673                 if(x.get()==obj)
674                         return *this;
675
676                 obj=x.get();
677                 return *this;
678         }
679
680         //! Swaps the values of two handles without reference counts
681         loose_handle<value_type> &
682         swap(loose_handle<value_type> &x)
683         {
684                 pointer ptr=x.obj;
685                 x.obj=x.get();
686                 obj=ptr;
687                 return *this;
688         }
689
690         //! Handle release procedure
691         void detach() { obj=0;  }
692
693         // This will be reintroduced with a new function
694         //void release() { detach(); }
695
696         void reset() { detach(); }
697
698         bool empty()const { return obj==0; }
699
700         handle<value_type> clone()const { assert(obj); return obj->clone(); }
701
702         //! Returns a constant handle to our object
703         loose_handle<const value_type> constant()const { return *this; }
704
705         //! Returns number of instances
706         count_type
707         count()const
708                 { return obj?obj->count():0; }
709
710         reference
711         operator*()const
712                 { assert(obj); return *obj; }
713
714         pointer
715         operator->()const
716                 { assert(obj); return obj; }
717
718         //! static_cast<> overload
719         //template <class U>
720         //operator loose_handle<U>()const
721         //{ return loose_handle<U>(static_cast<U*>(obj)); }
722
723         //! static_cast<> overload (for consts)
724         operator loose_handle<const value_type>()const
725         { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
726
727         operator handle<value_type>()const
728         { return handle<value_type>(obj); }
729
730         operator rhandle<value_type>()const
731         { return rhandle<value_type>(obj); }
732
733         //! Returns pointer to the object that is being wrapped
734         pointer get()const { return obj; }
735
736         //! More explicit bool cast
737         operator bool()const
738                 { return obj!=0; }
739
740         bool
741         operator!()const
742                 { return !obj; }
743
744         void ref() { if(obj)obj->ref(); }
745
746         bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
747 }; // END of template class loose_handle
748
749 // cast loose_handle<> -> handle<>
750 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())); }
751 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())); }
752 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())); }
753 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())); }
754
755 // cast rhandle_handle<> -> handle<>
756 template <class T> template <class U> handle<T> handle<T>::cast_static     (const rhandle<U>&      x) { return handle<T>(static_cast     <T*>(x.get())); }
757 template <class T> template <class U> handle<T> handle<T>::cast_dynamic    (const rhandle<U>&      x) { return handle<T>(dynamic_cast    <T*>(x.get())); }
758 template <class T> template <class U> handle<T> handle<T>::cast_const      (const rhandle<U>&      x) { return handle<T>(const_cast              <T*>(x.get())); }
759 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>&      x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
760
761 // cast U* -> handle<>
762 template <class T> template <class U> handle<T> handle<T>::cast_static     (U*                                     x) { return handle<T>(static_cast     <T*>(x));               }
763 template <class T> template <class U> handle<T> handle<T>::cast_dynamic    (U*                                     x) { return handle<T>(dynamic_cast    <T*>(x));               }
764 template <class T> template <class U> handle<T> handle<T>::cast_const      (U*                                     x) { return handle<T>(const_cast              <T*>(x));               }
765 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U*                                     x) { return handle<T>(reinterpret_cast<T*>(x));               }
766
767 // operator== for handle<>, loose_handle<> and T*
768 template <class T,class U> bool operator==(const handle          <T>& lhs,const handle          <U>& rhs) { return (lhs.get()==rhs.get()); }
769 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
770 template <class T,class U> bool operator==(const handle          <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
771 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle              <U>& rhs) { return (lhs.get()==rhs.get()); }
772 template <class T>                 bool operator==(const handle<T>&               lhs,const T*                           rhs) { return (lhs.get()==rhs);           }
773 template <class T>                 bool operator==(const loose_handle<T>& lhs,const T*                           rhs) { return (lhs.get()==rhs);           }
774 template <class T>                 bool operator==(const T*                               lhs,const handle<T>&           rhs) { return (lhs              ==rhs.get()); }
775 template <class T>                 bool operator==(const T*                               lhs,const loose_handle<T>& rhs) { return (lhs          ==rhs.get()); }
776
777 // operator!= for handle<>, loose_handle<> and T*
778 template <class T,class U> bool operator!=(const handle          <T>& lhs,const handle          <U>& rhs) { return (lhs.get()!=rhs.get()); }
779 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
780 template <class T,class U> bool operator!=(const handle          <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
781 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle              <U>& rhs) { return (lhs.get()!=rhs.get()); }
782 template <class T>                 bool operator!=(const handle<T>&               lhs,const T*                           rhs) { return (lhs.get()!=rhs);           }
783 template <class T>                 bool operator!=(const loose_handle<T>& lhs,const T*                           rhs) { return (lhs.get()!=rhs);           }
784 template <class T>                 bool operator!=(const T*                               lhs,const handle<T>&           rhs) { return (lhs              !=rhs.get()); }
785 template <class T>                 bool operator!=(const T*                               lhs,const loose_handle<T>& rhs) { return (lhs          !=rhs.get()); }
786
787 // operator< for handle<>, loose_handle<> and T*
788 template <class T,class U> bool operator<(const handle<T>&                lhs,const handle<U>&           rhs) { return (lhs.get()<rhs.get());  }
789 template <class T,class U> bool operator<(const loose_handle<T>&  lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get());  }
790 template <class T,class U> bool operator<(const handle<T>&                lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get());  }
791 template <class T,class U> bool operator<(const loose_handle<T>&  lhs,const handle<U>&           rhs) { return (lhs.get()<rhs.get());  }
792 template <class T>                 bool operator<(const handle<T>&                lhs,const T*                           rhs) { return (lhs.get()<rhs);            }
793 template <class T>                 bool operator<(const loose_handle<T>&  lhs,const T*                           rhs) { return (lhs.get()<rhs);            }
794 template <class T>                 bool operator<(const T*                                lhs,const handle<T>&           rhs) { return (lhs              <rhs.get());  }
795 template <class T>                 bool operator<(const T*                                lhs,const loose_handle<T>& rhs) { return (lhs          <rhs.get());  }
796
797 _ETL_END_NAMESPACE
798
799 /* === E N D =============================================================== */
800
801 #endif