- Main Page
- Related Pages
- Classes
- Files

# _handle.h

Go to the documentation of this file.

    00001 /* === E T L =============================================================== */
    00026 /* ========================================================================= */
    00027
    00028 /* === S T A R T =========================================================== */
    00029
    00030 #ifndef __ETL__HANDLE_H
    00031 #define __ETL__HANDLE_H
    00032
    00033 /* === H E A D E R S ======================================================= */
    00034
    00035 #include <cassert>
    00036
    00037 /* === M A C R O S ========================================================= */
    00038
    00039 /* === T Y P E D E F S ===================================================== */
    00040
    00041 #define ETL_SELF_DELETING_SHARED_OBJECT
    00042
    00043 /* === C L A S S E S & S T R U C T S ======================================= */
    00044
    00045 #ifdef NDEBUG
    00046 #define assert_cast     static_cast
    00047 #else
    00048 #define assert_cast     dynamic_cast
    00049 #endif
    00050
    00051
    00052 _ETL_BEGIN_NAMESPACE
    00053
    00054 // Forward Declarations
    00055 template <class T> class handle;
    00056 template <class T> class loose_handle;
    00057 template <class T> class rhandle;
    00058
    00059
    00060 // ========================================================================
    00066 class shared_object
    00067 {
    00068 private:
    00069     mutable int refcount;
    00070 #ifdef ETL_LOCK_REFCOUNTS
    00071     mutable etl::mutex mtx;
    00072 #endif
    00073
    00074 protected:
    00075     shared_object():refcount(0) { }
    00076
    00077 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
    00078     virtual ~shared_object() { }
    00079 #else
    00080     ~shared_object() { }
    00081 #endif
    00082
    00083 public:
    00084     void ref()const
    00085     {
    00086 #ifdef ETL_LOCK_REFCOUNTS
    00087         etl::mutex::lock lock(mtx);
    00088 #endif
    00089         assert(refcount>=0);
    00090         refcount++;
    00091     }
    00092
    00094     bool unref()const
    00095     {
    00096         bool ret = true;
    00097         {
    00098 #ifdef ETL_LOCK_REFCOUNTS
    00099             etl::mutex::lock lock(mtx);
    00100 #endif
    00101             assert(refcount>0);
    00102
    00103             refcount--;
    00104
    00105             if(refcount==0) {
    00106                 ret = false;
    00107 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
    00108                 refcount=-666;
    00109 #endif
    00110             }
    00111         }
    00112
    00113 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
    00114         if (!ret)
    00115             delete this;
    00116 #endif
    00117         return ret;
    00118     }
    00119
    00120     int count()const { return refcount; }
    00121
    00122 }; // END of class shared_object
    00123
    00124 // ========================================================================
    00130 class virtual_shared_object
    00131 {
    00132 protected:
    00133     virtual_shared_object() { }
    00134 public:
    00135     virtual ~virtual_shared_object()=0;
    00136     virtual void ref()const=0;
    00137     virtual bool unref()const=0;
    00138     virtual int count()const=0;
    00139     virtual virtual_shared_object *clone()=0;
    00140 }; // END of class virtual_shared_object
    00141
    00142 // ========================================================================
    00148 template <class T>
    00149 class handle
    00150 {
    00151 public:
    00152
    00153     typedef T value_type;
    00154     typedef T& reference;
    00155     typedef const T& const_reference;
    00156     typedef T* pointer;
    00157     typedef const T* const_pointer;
    00158     typedef int count_type;
    00159     typedef int size_type;
    00160
    00161 protected:
    00162 #ifdef _DEBUG
    00163 public:
    00164 #endif
    00165     value_type *obj;
    00166
    00167 public:
    00168
    00170     handle():obj(NULL) {}
    00171
    00173     handle(pointer x):obj(x)
    00174     {
    00175         if(obj)
    00176             obj->ref();
    00177     }
    00178
    00180     handle(const handle<value_type> &x):obj(x.get())
    00181     {
    00182         if(obj)
    00183             obj->ref();
    00184     }
    00185
    00187     ~handle() { detach(); }
    00188
    00190
    00193     /*
    00194     template <class U> handle<value_type> &
    00195     operator=(const handle<U> &x)
    00196     {
    00197         if(x.get()==obj)
    00198             return *this;
    00199
    00200         detach();
    00201
    00202         obj=static_cast<value_type*>(x.get());
    00203         if(obj)obj->ref();
    00204         return *this;
    00205     }
    00206     */
    00207
    00209     handle<value_type> &
    00210     operator=(const handle<value_type> &x)
    00211     {
    00212         if(x.get()==obj)
    00213             return *this;
    00214
    00215         detach();
    00216
    00217         obj=x.get();
    00218         if(obj)obj->ref();
    00219         return *this;
    00220     }
    00221
    00223     handle<value_type> &
    00224     swap(handle<value_type> &x)
    00225     {
    00226         pointer ptr=x.obj;
    00227         x.obj=obj;
    00228         obj=ptr;
    00229         return *this;
    00230     }
    00231
    00233
    00234     void
    00235     detach()
    00236     {
    00237         pointer xobj(obj);
    00238         obj=0;
    00239 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
    00240         if(xobj)
    00241             xobj->unref();
    00242 #else
    00243         if(xobj && !xobj->unref())
    00244             delete xobj;
    00245 #endif
    00246     }
    00247
    00248     // This will be reintroduced with a new function
    00249     //void release() { detach(); }
    00250
    00251     void reset() { detach(); }
    00252
    00253     bool empty()const { return obj==0; }
    00254
    00256
    00257     void spawn() { operator=(handle(new T())); }
    00258
    00259     handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
    00260
    00262     handle<const value_type> constant()const { assert(obj); return *this; }
    00263
    00265     count_type
    00266     count()const
    00267         { return obj?obj->count():0; }
    00268
    00270     bool
    00271     unique()const
    00272         { assert(obj); return count()==1; }
    00273
    00274     reference
    00275     operator*()const
    00276         { assert(obj); return *obj; }
    00277
    00278     pointer
    00279     operator->()const
    00280         { assert(obj); return obj; }
    00281
    00283     operator bool()const
    00284         { return obj!=NULL; }
    00285
    00286     operator handle<const value_type>()const
    00287     { return handle<const value_type>(static_cast<const_pointer>(obj)); }
    00288
    00290     template <class U> static handle<T> cast_static     (const handle<U> &x) { return handle<T>(static_cast     <T*>(x.get())); }
    00292     template <class U> static handle<T> cast_dynamic    (const handle<U> &x) { return handle<T>(dynamic_cast    <T*>(x.get())); }
    00294     template <class U> static handle<T> cast_const      (const handle<U> &x) { return handle<T>(const_cast      <T*>(x.get())); }
    00296     template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
    00297
    00298     template <class U> static handle<T> cast_static     (const loose_handle<U> &x);
    00299     template <class U> static handle<T> cast_dynamic    (const loose_handle<U> &x);
    00300     template <class U> static handle<T> cast_const      (const loose_handle<U> &x);
    00301     template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
    00302
    00303     template <class U> static handle<T> cast_static     (const rhandle<U> &x);
    00304     template <class U> static handle<T> cast_dynamic    (const rhandle<U> &x);
    00305     template <class U> static handle<T> cast_const      (const rhandle<U> &x);
    00306     template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
    00307
    00308     template <class U> static handle<T> cast_static     (U* x);
    00309     template <class U> static handle<T> cast_dynamic    (U* x);
    00310     template <class U> static handle<T> cast_const      (U* x);
    00311     template <class U> static handle<T> cast_reinterpret(U* x);
    00312
    00314     pointer get()const { return obj; }
    00315
    00316     bool
    00317     operator!()const
    00318         { return !obj; }
    00319
    00321     template <class U>
    00322     operator handle<U>()const
    00323     { return handle<U>(static_cast<U*>(obj)); }
    00324 }; // END of template class handle
    00325
    00326 // ========================================================================
    00332 class rshared_object : public shared_object
    00333 {
    00334 private:
    00335     mutable int rrefcount;
    00336
    00337 public:
    00338     void *front_;
    00339     void *back_;
    00340
    00341 protected:
    00342     rshared_object():rrefcount(0),front_(0),back_(0) { }
    00343
    00344 public:
    00345     void rref()const
    00346         { rrefcount++; }
    00347
    00348     void runref()const
    00349     {
    00350         assert(rrefcount>0);
    00351         rrefcount--;
    00352     }
    00353
    00354     int rcount()const
    00355         { return rrefcount; }
    00356 }; // END of class rshared_object
    00357
    00358 // ========================================================================
    00364 template <class T>
    00365 class rhandle : public handle<T>
    00366 {
    00367     friend class rshared_object;
    00368 public:
    00369
    00370     typedef T value_type;
    00371     typedef T& reference;
    00372     typedef const T& const_reference;
    00373     typedef T* pointer;
    00374     typedef const T* const_pointer;
    00375     typedef int count_type;
    00376     typedef int size_type;
    00377
    00378
    00379     using handle<value_type>::count;
    00380     using handle<value_type>::unique;
    00381     using handle<value_type>::operator bool;
    00382     using handle<value_type>::get;
    00383     using handle<value_type>::operator*;
    00384     using handle<value_type>::operator->;
    00385
    00386     /*
    00387     operator const handle<value_type>&()const
    00388     { return *this; }
    00389     */
    00390
    00391 private:
    00392     using handle<value_type>::obj;
    00393
    00394     rhandle<value_type> *prev_;
    00395     rhandle<value_type> *next_;
    00396
    00397     void add_to_rlist()
    00398     {
    00399 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00400
    00401         assert(obj);
    00402         obj->rref();
    00403
    00404         // If this is the first reversible handle
    00405         if(!obj->front_)
    00406         {
    00407             obj->front_=obj->back_=this;
    00408             prev_=next_=0;
    00409             return;
    00410         }
    00411
    00412         prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
    00413         next_=0;
    00414         prev_->next_=this;
    00415         obj->back_=this;
    00416     }
    00417
    00418     void del_from_rlist()
    00419     {
    00420 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00421         assert(obj);
    00422         obj->runref();
    00423
    00424         // If this is the last reversible handle
    00425         if(obj->front_==obj->back_)
    00426         {
    00427             obj->front_=obj->back_=0;
    00428             prev_=next_=0;
    00429             return;
    00430         }
    00431
    00432         if(!prev_)
    00433             obj->front_=(void*)next_;
    00434         else
    00435             prev_->next_=next_;
    00436
    00437         if(!next_)
    00438             obj->back_=(void*)prev_;
    00439         else
    00440             next_->prev_=prev_;
    00441     }
    00442
    00443 public:
    00444
    00446     rhandle() {}
    00447
    00449     rhandle(pointer x):handle<T>(x)
    00450     {
    00451 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00452         if(obj)add_to_rlist();
    00453     }
    00454
    00455     rhandle(const handle<value_type> &x):handle<T>(x)
    00456     {
    00457 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00458         if(obj)add_to_rlist();
    00459     }
    00460
    00462     rhandle(const rhandle<value_type> &x):handle<T>(x)
    00463     {
    00464 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00465         if(obj)add_to_rlist();
    00466     }
    00467
    00469     ~rhandle() { detach(); }
    00470
    00472
    00475     /*
    00476     template <class U> const handle<value_type> &
    00477     operator=(const handle<U> &x)
    00478     {
    00479         if(x.get()==obj)
    00480             return *this;
    00481
    00482         detach();
    00483
    00484         obj=static_cast<value_type*>(x.get());
    00485         if(obj)
    00486         {
    00487             obj->ref();
    00488             add_to_rlist();
    00489         }
    00490         return *this;
    00491     }
    00492     */
    00493
    00495     rhandle<value_type> &
    00496     operator=(const rhandle<value_type> &x)
    00497     {
    00498 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00499         if(x.get()==obj)
    00500             return *this;
    00501
    00502         detach();
    00503
    00504         obj=x.get();
    00505         if(obj)
    00506         {
    00507             obj->ref();
    00508             add_to_rlist();
    00509         }
    00510         return *this;
    00511     }
    00512
    00513     rhandle<value_type>&
    00514     operator=(const handle<value_type> &x)
    00515     {
    00516 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00517         if(x.get()==obj)
    00518             return *this;
    00519
    00520         detach();
    00521
    00522         obj=x.get();
    00523         if(obj)
    00524         {
    00525             obj->ref();
    00526             add_to_rlist();
    00527         }
    00528         return *this;
    00529     }
    00530
    00531     rhandle<value_type>&
    00532     operator=(value_type* x)
    00533     {
    00534 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00535         if(x==obj)
    00536             return *this;
    00537
    00538         detach();
    00539
    00540         obj=x;
    00541         if(obj)
    00542         {
    00543             obj->ref();
    00544             add_to_rlist();
    00545         }
    00546         return *this;
    00547     }
    00548
    00550
    00551     void
    00552     detach()
    00553     {
    00554 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00555         if(obj)del_from_rlist();
    00556         handle<value_type>::detach();
    00557         obj=0;
    00558     }
    00559
    00560     // This will be reintroduced with a new function
    00561     //void release() { detach(); }
    00562
    00563     void reset() { detach(); }
    00564
    00566
    00567     void spawn() { operator=(handle<value_type>(new T())); }
    00568
    00570     count_type
    00571     rcount()const
    00572     {
    00573 //      value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00574         return obj?obj->rcount():0;
    00575     }
    00576
    00578     bool
    00579     runique()const
    00580     {
    00581 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00582         assert(obj); return obj->front_==obj->back_;
    00583     }
    00584
    00586     int replace(const handle<value_type> &x)
    00587     {
    00588 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
    00589         assert(obj);
    00590         assert(x.get()!=obj);
    00591
    00592         if(x.get()==obj)
    00593             return 0;
    00594
    00595         rhandle<value_type> *iter;
    00596         rhandle<value_type> *next;
    00597
    00598         iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
    00599
    00600         assert(iter);
    00601
    00602         next=iter->next_;
    00603
    00604         int i=0;
    00605         #ifndef NDEBUG
    00606         pointer obj_=obj;
    00607         #endif
    00608
    00609         for(;iter;iter=next,next=iter?iter->next_:0,i++)
    00610         {
    00611             assert(iter->get()==obj_);
    00612             (*iter)=x;
    00613         }
    00614
    00615         assert(obj==x.get());
    00616
    00617         return i;
    00618     }
    00619
    00621
    00622     handle<value_type> &
    00623     swap(handle<value_type> &x);
    00624     /*
    00625     {
    00626         assert(0);
    00627         pointer ptr=x.obj;
    00628         x.obj=obj;
    00629         obj=ptr;
    00630         return *this;
    00631     }
    00632     */
    00633 }; // END of template class rhandle
    00634
    00635
    00636 // ========================================================================
    00642 template <class T>
    00643 class loose_handle
    00644 {
    00645 public:
    00646
    00647     typedef T value_type;
    00648     typedef T& reference;
    00649     typedef const T& const_reference;
    00650     typedef T* pointer;
    00651     typedef const T* const_pointer;
    00652     typedef int count_type;
    00653     typedef int size_type;
    00654
    00655 protected:
    00656 #ifdef _DEBUG
    00657 public:
    00658 #endif
    00659     value_type *obj;
    00660
    00661 public:
    00662
    00664     loose_handle():obj(0) {}
    00665
    00667     loose_handle(pointer x):obj(x) { }
    00668
    00670     loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
    00671
    00672     loose_handle(const handle<value_type> &x):obj(x.get()) { }
    00673
    00674     template <class U> const loose_handle<value_type> &
    00675     operator=(const handle<U> &x)
    00676     {
    00677         if(x.get()==obj)
    00678             return *this;
    00679
    00680         obj=static_cast<value_type*>(x.get());
    00681         return *this;
    00682     }
    00683
    00684     template <class U> const loose_handle<value_type> &
    00685     operator=(const loose_handle<U> &x)
    00686     {
    00687         if(x.get()==obj)
    00688             return *this;
    00689
    00690         obj=static_cast<value_type*>(x.get());
    00691         return *this;
    00692     }
    00693
    00695     const loose_handle<value_type> &
    00696     operator=(const loose_handle<value_type> &x)
    00697     {
    00698         if(x.get()==obj)
    00699             return *this;
    00700
    00701         obj=x.get();
    00702         return *this;
    00703     }
    00704
    00706     loose_handle<value_type> &
    00707     swap(loose_handle<value_type> &x)
    00708     {
    00709         pointer ptr=x.obj;
    00710         x.obj=obj;
    00711         obj=ptr;
    00712         return *this;
    00713     }
    00714
    00716     void detach() { obj=0;  }
    00717
    00718     // This will be reintroduced with a new function
    00719     //void release() { detach(); }
    00720
    00721     void reset() { detach(); }
    00722
    00723     bool empty()const { return obj==0; }
    00724
    00725     handle<value_type> clone()const { assert(obj); return obj->clone(); }
    00726
    00728     loose_handle<const value_type> constant()const { return *this; }
    00729
    00731     count_type
    00732     count()const
    00733         { return obj?obj->count():0; }
    00734
    00735     reference
    00736     operator*()const
    00737         { assert(obj); return *obj; }
    00738
    00739     pointer
    00740     operator->()const
    00741         { assert(obj); return obj; }
    00742
    00744     //template <class U>
    00745     //operator loose_handle<U>()const
    00746     //{ return loose_handle<U>(static_cast<U*>(obj)); }
    00747
    00749     operator loose_handle<const value_type>()const
    00750     { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
    00751
    00752     operator handle<value_type>()const
    00753     { return handle<value_type>(obj); }
    00754
    00755     operator rhandle<value_type>()const
    00756     { return rhandle<value_type>(obj); }
    00757
    00759     pointer get()const { return obj; }
    00760
    00762     operator bool()const
    00763         { return obj!=0; }
    00764
    00765     bool
    00766     operator!()const
    00767         { return !obj; }
    00768
    00769     void ref() { if(obj)obj->ref(); }
    00770
    00771     bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
    00772 }; // END of template class loose_handle
    00773
    00774 // cast loose_handle<> -> handle<>
    00775 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())); }
    00776 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())); }
    00777 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())); }
    00778 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())); }
    00779
    00780 // cast rhandle_handle<> -> handle<>
    00781 template <class T> template <class U> handle<T> handle<T>::cast_static     (const rhandle<U>&      x) { return handle<T>(static_cast     <T*>(x.get())); }
    00782 template <class T> template <class U> handle<T> handle<T>::cast_dynamic    (const rhandle<U>&      x) { return handle<T>(dynamic_cast    <T*>(x.get())); }
    00783 template <class T> template <class U> handle<T> handle<T>::cast_const      (const rhandle<U>&      x) { return handle<T>(const_cast      <T*>(x.get())); }
    00784 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>&      x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
    00785
    00786 // cast U* -> handle<>
    00787 template <class T> template <class U> handle<T> handle<T>::cast_static     (U*                     x) { return handle<T>(static_cast     <T*>(x));       }
    00788 template <class T> template <class U> handle<T> handle<T>::cast_dynamic    (U*                     x) { return handle<T>(dynamic_cast    <T*>(x));       }
    00789 template <class T> template <class U> handle<T> handle<T>::cast_const      (U*                     x) { return handle<T>(const_cast      <T*>(x));       }
    00790 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U*                     x) { return handle<T>(reinterpret_cast<T*>(x));       }
    00791
    00792 // operator== for handle<>, loose_handle<> and T*
    00793 template <class T,class U> bool operator==(const handle      <T>& lhs,const handle      <U>& rhs) { return (lhs.get()==rhs.get()); }
    00794 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
    00795 template <class T,class U> bool operator==(const handle      <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
    00796 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle      <U>& rhs) { return (lhs.get()==rhs.get()); }
    00797 template <class T>         bool operator==(const handle<T>&       lhs,const T*               rhs) { return (lhs.get()==rhs);       }
    00798 template <class T>         bool operator==(const loose_handle<T>& lhs,const T*               rhs) { return (lhs.get()==rhs);       }
    00799 template <class T>         bool operator==(const T*               lhs,const handle<T>&       rhs) { return (lhs      ==rhs.get()); }
    00800 template <class T>         bool operator==(const T*               lhs,const loose_handle<T>& rhs) { return (lhs      ==rhs.get()); }
    00801
    00802 // operator!= for handle<>, loose_handle<> and T*
    00803 template <class T,class U> bool operator!=(const handle      <T>& lhs,const handle      <U>& rhs) { return (lhs.get()!=rhs.get()); }
    00804 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
    00805 template <class T,class U> bool operator!=(const handle      <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
    00806 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle      <U>& rhs) { return (lhs.get()!=rhs.get()); }
    00807 template <class T>         bool operator!=(const handle<T>&       lhs,const T*               rhs) { return (lhs.get()!=rhs);       }
    00808 template <class T>         bool operator!=(const loose_handle<T>& lhs,const T*               rhs) { return (lhs.get()!=rhs);       }
    00809 template <class T>         bool operator!=(const T*               lhs,const handle<T>&       rhs) { return (lhs      !=rhs.get()); }
    00810 template <class T>         bool operator!=(const T*               lhs,const loose_handle<T>& rhs) { return (lhs      !=rhs.get()); }
    00811
    00812 // operator< for handle<>, loose_handle<> and T*
    00813 template <class T,class U> bool operator<(const handle<T>&        lhs,const handle<U>&       rhs) { return (lhs.get()<rhs.get());  }
    00814 template <class T,class U> bool operator<(const loose_handle<T>&  lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get());  }
    00815 template <class T,class U> bool operator<(const handle<T>&        lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get());  }
    00816 template <class T,class U> bool operator<(const loose_handle<T>&  lhs,const handle<U>&       rhs) { return (lhs.get()<rhs.get());  }
    00817 template <class T>         bool operator<(const handle<T>&        lhs,const T*               rhs) { return (lhs.get()<rhs);        }
    00818 template <class T>         bool operator<(const loose_handle<T>&  lhs,const T*               rhs) { return (lhs.get()<rhs);        }
    00819 template <class T>         bool operator<(const T*                lhs,const handle<T>&       rhs) { return (lhs      <rhs.get());  }
    00820 template <class T>         bool operator<(const T*                lhs,const loose_handle<T>& rhs) { return (lhs      <rhs.get());  }
    00821
    00822 _ETL_END_NAMESPACE
    00823
    00824 /* === E N D =============================================================== */
    00825
    00826 #endif