Mirror reflection library 0.5.13
|
00001 00010 #ifndef MIRROR_UTILS_SOME_TYPE_1113061708_HPP 00011 #define MIRROR_UTILS_SOME_TYPE_1113061708_HPP 00012 00013 #include <mirror/config.hpp> 00014 #include <boost/any.hpp> 00015 #include <type_traits> 00016 #include <stdexcept> 00017 00018 MIRROR_NAMESPACE_BEGIN 00019 00021 00034 class some 00035 { 00036 private: 00037 boost::any val_or_ptr; 00038 00039 boost::any (*copier)(const boost::any&); 00040 00041 template <typename T> 00042 static boost::any copy_or_throw(const boost::any& a, std::true_type) 00043 { 00044 return boost::any(*boost::any_cast<T*>(a)); 00045 } 00046 00047 static void do_throw(void) 00048 { 00049 throw std::runtime_error("some: Unable to copy stored value"); 00050 } 00051 00052 template <typename T> 00053 static boost::any copy_or_throw(const boost::any& a, std::false_type) 00054 { 00055 do_throw(); 00056 return boost::any(); 00057 } 00058 00059 template <typename T> 00060 static boost::any do_copy(const boost::any& pointer) 00061 { 00062 return copy_or_throw<T>( 00063 pointer, 00064 typename mirror::is_copy_constructible<T>::type() 00065 ); 00066 } 00067 00068 bool const_; 00069 bool by_ptr; 00070 00071 bool is_sane(void) const 00072 { 00073 return empty() || !by_ptr || (copier != nullptr); 00074 } 00075 00076 void do_detach(void) 00077 { 00078 assert(copier != nullptr); 00079 val_or_ptr = copier(val_or_ptr); 00080 copier = nullptr; 00081 const_ = false; 00082 by_ptr = false; 00083 assert(is_sane()); 00084 } 00085 00086 some(const boost::any& a) 00087 : val_or_ptr(a) 00088 , copier(nullptr) 00089 , const_(false) 00090 , by_ptr(false) 00091 { 00092 assert(is_sane()); 00093 } 00094 public: 00096 00102 some(void) 00103 : copier(nullptr) 00104 , const_(false) 00105 , by_ptr(false) 00106 { 00107 assert(is_sane()); 00108 } 00109 00111 00119 template <typename T> 00120 some(T value, std::false_type = std::false_type()) 00121 : val_or_ptr(value) 00122 , copier(nullptr) 00123 , const_(std::is_const<T>::value) 00124 , by_ptr(false) 00125 { 00126 assert(is_sane()); 00127 } 00128 00130 00142 template <typename T> 00143 some(T& inst, std::true_type by_ptr) 00144 : val_or_ptr(&const_cast<typename std::remove_cv<T>::type&>(inst)) 00145 , copier(&do_copy<typename std::remove_cv<T>::type>) 00146 , const_(false) 00147 , by_ptr(true) 00148 { 00149 assert(is_sane()); 00150 } 00151 00153 00165 template <typename T> 00166 some(const T& inst, std::true_type by_ptr) 00167 : val_or_ptr(&const_cast<typename std::remove_cv<T>::type&>(inst)) 00168 , copier(&do_copy<typename std::remove_cv<T>::type>) 00169 , const_(true) 00170 , by_ptr(true) 00171 { 00172 assert(is_sane()); 00173 } 00174 00175 #ifdef MIRROR_DOCUMENTATION_ONLY 00176 00177 00183 bool empty(void) const; 00184 #else 00185 inline auto empty(void) const -> 00186 decltype(val_or_ptr.empty()) 00187 { 00188 return val_or_ptr.empty(); 00189 } 00190 #endif 00191 00193 00205 inline bool standalone(void) const 00206 { 00207 return !by_ptr; 00208 } 00209 00211 00218 inline some& detach(void) 00219 { 00220 if(by_ptr && !empty()) do_detach(); 00221 return *this; 00222 } 00223 00225 00233 inline bool is_const(void) const 00234 { 00235 return const_; 00236 } 00237 00239 00250 inline bool is_reference(void) const 00251 { 00252 return by_ptr && !const_; 00253 } 00254 00256 00273 inline bool is_value(void) const 00274 { 00275 return !empty() && !is_reference(); 00276 } 00277 00279 00287 template <typename T> 00288 inline bool is(void) const 00289 { 00290 return val_or_ptr.type() == typeid(T*) || 00291 val_or_ptr.type() == typeid(T); 00292 } 00293 00294 #ifdef MIRROR_DOCUMENTATION_ONLY 00295 00296 00309 template <typename T> 00310 friend T-or-T& some_cast(some& s); 00311 #else 00312 template <typename T> 00313 friend typename std::remove_volatile< 00314 typename std::remove_reference<T>::type 00315 >::type& some_cast(some& s) 00316 { 00317 assert(!s.val_or_ptr.empty()); 00318 assert(s.is_sane()); 00319 typedef typename std::remove_volatile< 00320 typename std::remove_reference<T>::type 00321 >::type type; 00322 typedef typename std::remove_const<type>::type type_; 00323 bool const_ok = !s.const_ || std::is_const<type>::value; 00324 if(s.val_or_ptr.type() == typeid(type_*) && const_ok) 00325 return *boost::any_cast<type_*>(s.val_or_ptr); 00326 else return boost::any_cast<type&>(s.val_or_ptr); 00327 } 00328 #endif 00329 00330 #ifdef MIRROR_DOCUMENTATION_ONLY 00331 00332 00342 template <typename T> 00343 friend T some_cast(const some& s); 00344 #else 00345 template <typename T> 00346 friend const typename std::remove_cv< 00347 typename std::remove_reference<T>::type 00348 >::type& some_cast(const some& s) 00349 { 00350 assert(!s.val_or_ptr.empty()); 00351 assert(s.is_sane()); 00352 typedef typename std::remove_cv< 00353 typename std::remove_reference<T>::type 00354 >::type type; 00355 if(s.val_or_ptr.type() == typeid(type*)) 00356 return *boost::any_cast<type*>(s.val_or_ptr); 00357 else return boost::any_cast<const type&>(s.val_or_ptr); 00358 } 00359 #endif 00360 00361 #ifdef MIRROR_DOCUMENTATION_ONLY 00362 00363 00373 template <typename T> 00374 T as(const some& s) const; 00375 #else 00376 template <typename T> 00377 inline const typename std::remove_cv< 00378 typename std::remove_reference<T>::type 00379 >::type& as(void) const 00380 { 00381 return some_cast<const T>(*this); 00382 } 00383 #endif 00384 }; 00385 00386 template <typename T> 00387 some some_ref(T& ref) 00388 { 00389 return some(ref, std::true_type()); 00390 } 00391 00392 MIRROR_NAMESPACE_END 00393 00394 #endif //include guard 00395