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