00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00040 #ifndef LUMIERA_VARIANT_H
00041 #define LUMIERA_VARIANT_H
00042
00043
00044 #include "common/meta/typelistutil.hpp"
00045 #include "common/meta/generator.hpp"
00046
00047 #include <boost/noncopyable.hpp>
00048
00049
00050
00051 namespace lumiera {
00052
00053 namespace variant {
00054
00055 using lumiera::typelist::count;
00056 using lumiera::typelist::maxSize;
00057 using lumiera::typelist::InstantiateWithIndex;
00058
00068 template<typename TYPES>
00069 struct Holder
00070 {
00071
00072 enum { TYPECNT = count<TYPES>::value
00073 , SIZE = maxSize<TYPES>::value
00074 };
00075
00076
00078 struct Buffer
00079 {
00080 char buffer_[SIZE];
00081 uint which_;
00082
00083 Buffer() : which_(TYPECNT) {}
00084
00085 void*
00086 put (void)
00087 {
00088 deleteCurrent();
00089 return 0;
00090 }
00091
00092 void
00093 deleteCurrent ();
00094 };
00095
00096 template<typename T, class BASE, uint idx>
00097 struct PlacementAdapter : BASE
00098 {
00099 T&
00100 put (T const& toStore)
00101 {
00102 BASE::deleteCurrent();
00103
00104 T& storedObj = *new(BASE::buffer_) T (toStore);
00105 BASE::which_ = idx;
00106 return storedObj;
00107 }
00108
00109 using BASE::put;
00110 };
00111
00112 typedef InstantiateWithIndex< TYPES
00113 , PlacementAdapter
00114 , Buffer
00115 >
00116 Storage;
00117
00118
00119
00121 template<class FUNCTOR>
00122 struct CaseSelect
00123 {
00124 typedef typename FUNCTOR::Ret Ret;
00125 typedef Ret (*Func)(Buffer&);
00126
00127 Func table_[TYPECNT];
00128
00129 CaseSelect ()
00130 {
00131 for (uint i=0; i<TYPECNT; ++i)
00132 table_[i] = 0;
00133 }
00134
00135 template<typename T>
00136 static Ret
00137 trampoline (Buffer& storage)
00138 {
00139 T& content = reinterpret_cast<T&> (storage.buffer_);
00140 return FUNCTOR::access (content);
00141 }
00142
00143 Ret
00144 invoke (Buffer& storage)
00145 {
00146 if (TYPECNT <= storage.which_)
00147 return FUNCTOR::ifEmpty ();
00148 else
00149 return (*table_[storage.which_]) (storage);
00150 }
00151 };
00152
00153
00154 template< class T, class BASE, uint i >
00155 struct CasePrepare
00156 : BASE
00157 {
00158 CasePrepare () : BASE()
00159 {
00160 BASE::table_[i] = &BASE::template trampoline<T>;
00161 }
00162 };
00163
00164
00165 template<class FUNCTOR>
00166 static typename FUNCTOR::Ret
00167 access (Buffer& buf)
00168 {
00169 typedef InstantiateWithIndex< TYPES
00170 , CasePrepare
00171 , CaseSelect<FUNCTOR>
00172 >
00173 Accessor;
00174 static Accessor select_case;
00175 return select_case.invoke(buf);
00176 }
00177
00178
00179 struct Deleter
00180 {
00181 typedef void Ret;
00182
00183 template<typename T>
00184 static void access (T& elem) { elem.~T(); }
00185
00186 static void ifEmpty () { }
00187 };
00188 };
00189
00190
00191 template<typename TYPES>
00192 inline void
00193 Holder<TYPES>::Buffer::deleteCurrent ()
00194 {
00195 access<Deleter>(*this);
00196 which_ = TYPECNT;
00197 }
00198
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00226 template< typename TYPES
00227 , template<typename> class Access
00228 >
00229 class Variant
00230 : boost::noncopyable
00231 {
00232
00233 typedef variant::Holder<TYPES> Holder;
00234 typedef typename Holder::Deleter Deleter;
00235
00236
00239 typename Holder::Storage holder_;
00240
00241
00242 public:
00243 void reset () { holder_.deleteCurrent();}
00244
00251 template<typename SRC>
00252 Variant&
00253 operator= (SRC src)
00254 {
00255 if (src) holder_.put (src);
00256 else reset();
00257 return *this;
00258 }
00259
00267 template<typename TAR>
00268 TAR
00269 get ()
00270 {
00271 typedef Access<TAR> Extractor;
00272 return Holder::template access<Extractor> (this->holder_);
00273 }
00274 };
00275
00276 }
00277 #endif