Mirror reflection library 0.5.13

mirror/utils/some_type.hpp

Go to the documentation of this file.
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 

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.