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