Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

d_Variant.h

Go to the documentation of this file.
00001 
00002 #ifndef d_Variant_h
00003 #define d_Variant_h 1
00004 //------------------------------------------------------------------------------
00005 #include <iostream>
00006 
00007 #include "oLibrary.h"
00008 
00009 //------------------------------------------------------------------------------
00010 class _ODLL d_Variant
00011 {
00012   public :
00013     d_Variant() : data(0) {}
00014 
00015     d_Variant( const d_Variant & rhs )
00016     {
00017       if( rhs.data )
00018         rhs.data->AddRef();
00019       data = rhs.data;
00020     }
00021 
00022     ~d_Variant()
00023     {
00024       if( data )
00025         data->Release();
00026     }
00027  
00028     // NOTE: This code takes care of self-asignment.
00029     // DO NOT CHANGE THE ORDER of the statements.
00030     d_Variant& operator = ( const d_Variant& rhs )
00031     {
00032       if( rhs.data )
00033         rhs.data->AddRef();
00034       if( data )
00035         data->Release();
00036       data = rhs.data;
00037       return *this;
00038     }
00039 
00040     // This member template constructor allows you to
00041     // instance a d_Variant object with a value of any type.
00042     template<typename T> d_Variant ( T v )
00043       : data ( new Impl<T>(v) )
00044       { data->AddRef() ; }
00045 
00046     // This generic conversion operator let you retrieve
00047     // the value held.
00048     // To avoid template specialization conflicts, it
00049     // returns an instance of type T, which will be a COPY
00050     // of the value contained.
00051     template<typename T> operator T () const
00052       { return CastFromBase<T>( data )->data ; }
00053 
00054     // With expressions of the form: int a = my_variant ,
00055     // the compiler needs to take the template argument T
00056     // from the type of the left side of the assigment.
00057     // Most compilers won't do that, so you might need this
00058     // non-operator form, as in:
00059     // int a = my_variant.get<int>();
00060     // This forms returns a REFERENCE and not a COPY, which
00061     // will be significant in some cases.
00062     template<typename T> const T& get() const
00063       { return CastFromBase<T>( data )->data ; }
00064 
00065     char* raw() const;
00066 
00067     // This method can be used to test if this d_Variant
00068     // holds a value of type T. It takes no arguments,
00069     // so it can only be used with a explicit template
00070     // instancing:
00071     //   d_Variant var(3) ; if ( var.is_type<int>() ) ...
00072     template<typename T> bool is_type() const
00073       { return typeid(*data)==typeid(Impl<T>); }
00074 
00075     // This method can be used to test if this d_Variant
00076     // holds a value of type T.
00077     // It takes one argument, so it can be used with
00078     // a test variable of the desired type:
00079     //   int n=3; d_Variant var(n) ;
00080     //   if ( var.is_type(n) ) ...
00081     template<typename T> bool is_type(T v) const
00082       { return typeid(*data)==typeid(v); }
00083 
00084   private :
00085 
00086     // This base class provides polymorphism to Impl<>, due
00087     // to the virtual destructor.
00088     // It implements the reference counting over Impl<>.
00089     struct ImplBase
00090     {
00091       ImplBase() : refs ( 0 ) {}
00092       virtual ~ImplBase() {}
00093       void AddRef () { refs ++ ; }
00094       void Release() { refs -- ;
00095                        if ( refs == 0 )
00096                          delete this ;
00097                      }
00098       size_t refs ;
00099     } ;
00100 
00101     // An instance of Impl<T> is just a straight copy of a
00102     // value of type T, but re-typed as a polymorphic type.
00103     // As long as the copy constructor for T is properly
00104     // implemented, the value will be properly copied.
00105     template<typename T>
00106     struct Impl : ImplBase
00107     {
00108        Impl ( T v ) : data ( v ) {}
00109       ~Impl () {}
00110       T data ;
00111     } ;
00112 
00113     // The following 2 methods are static because they don't
00114     // operate on d_Variant instances.
00115     template<typename T>
00116     static ImplBase* CastToBase ( Impl<T>* v )
00117       { return v ; } // Implicit convertion here
00118 
00119     template<typename T>
00120     static Impl<T>* CastFromBase ( ImplBase* v )
00121     {
00122       // This upcast will fail if T is other than the T used
00123       // with the constructor of d_Variant.
00124       Impl<T>* p = dynamic_cast<Impl<T>*> ( v ) ;
00125       if ( p == 0 )
00126         throw invalid_argument
00127          ( typeid(T).name()+string(" is not a valid type"));
00128       return p ;
00129     }
00130 
00131     ImplBase* data;
00132 };
00133 
00134 //------------------------------------------------------------------------------
00135 #endif
00136 //------------------------------------------------------------------------------
00137 //------------------------------------------------------------------------------

Generated on Fri Nov 29 17:12:13 2002 for Orient ODBMS Just Edition v. 2.0e by doxygen1.3-rc1