lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
any.h
00001 /*****************************************************/
00002 /* lean Containers              (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_CONTAINERS_ANY
00006 #define LEAN_CONTAINERS_ANY
00007 
00008 #include "../lean.h"
00009 #include "../meta/strip.h"
00010 #include "../smart/cloneable.h"
00011 #include "../memory/heap_bound.h"
00012 #include <typeinfo>
00013 
00014 namespace lean
00015 {
00016 namespace containers
00017 {
00018 
00020 class any : public cloneable
00021 {
00022     template <class Value>
00023     friend Value* any_cast(any*);
00024 
00025 protected:
00026     LEAN_INLINE any& operator =(const any&) { return *this; }
00027 
00029     virtual void* get_any_ptr(const std::type_info& type) = 0;
00030 
00031 public:
00032     virtual ~any() { }
00033     
00035     virtual const std::type_info& type() const = 0;
00036 };
00037 
00039 template <class Value, class Heap = default_heap>
00040 class any_value : public heap_bound<Heap>, public any
00041 {
00042 private:
00043     Value m_value;
00044 
00045 protected:
00047     void* get_any_ptr(const std::type_info& type)
00048     {
00049         return (typeid(Value) == type)
00050             ? &m_value
00051             : nullptr;
00052     }
00053 
00054 public:
00056     typedef Value value_type;
00057 
00059     LEAN_INLINE any_value()
00060         : m_value() { }
00062     LEAN_INLINE any_value(const value_type &value)
00063         : m_value(value) { }
00064 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00065 
00066     LEAN_INLINE any_value(value_type &&value)
00067         : m_value(std::move(value)) { }
00068 #endif
00069 
00071     LEAN_INLINE any_value& operator =(const value_type &value)
00072     {
00073         m_value = value;
00074         return *this;
00075     }
00076 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00077 
00078     LEAN_INLINE any_value& operator =(value_type &&value)
00079     {
00080         m_value = std::move(value);
00081         return *this;
00082     }
00083 #endif
00084 
00086     LEAN_INLINE value_type& get() { return m_value; }
00088     LEAN_INLINE const value_type& get() const { return m_value; }
00090     LEAN_INLINE volatile value_type& get() volatile { return m_value; }
00092     LEAN_INLINE const volatile value_type& get() const volatile { return m_value; }
00093 
00095     LEAN_INLINE const std::type_info& type() const
00096     {
00097         return typeid(value_type);
00098     }
00099 
00101     LEAN_INLINE any_value* clone() const { return new any_value(*this); }
00103     LEAN_INLINE void destroy() const { delete this; }
00104 };
00105 
00107 template <class Value>
00108 LEAN_INLINE Value* any_cast(any *pContainer)
00109 {
00110     return static_cast<Value*>(
00111         pContainer
00112             ? pContainer->get_any_ptr(typeid(Value))
00113             : nullptr );
00114 }
00116 template <class Value>
00117 LEAN_INLINE const Value* any_cast(const any *pContainer)
00118 {
00119     return any_cast<const Value>(const_cast<any*>(pContainer));
00120 }
00122 template <class Value>
00123 LEAN_INLINE volatile Value* any_cast(volatile any *pContainer)
00124 {
00125     return any_cast<volatile Value>(const_cast<any*>(pContainer));
00126 }
00128 template <class Value>
00129 LEAN_INLINE const volatile Value* any_cast(const volatile any *pContainer)
00130 {
00131     return any_cast<const volatile Value>(const_cast<any*>(pContainer));
00132 }
00133 
00134 namespace impl
00135 {
00137     LEAN_NOINLINE void throw_bad_cast()
00138     {
00139         throw std::bad_cast();
00140     }
00141 
00142 } // namespace
00143 
00145 template <class Value>
00146 LEAN_INLINE Value any_cast_checked(any *container)
00147 {
00148     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00149     nonref_value_type *pValue = any_cast<nonref_value_type>(container);
00150     
00151     if (!pValue)
00152         impl::throw_bad_cast();
00153 
00154     return *pValue;
00155 }
00157 template <class Value>
00158 LEAN_INLINE Value any_cast_checked(const any *container)
00159 {
00160     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00161     return any_cast_checked<const nonref_value_type&>(const_cast<any*>(container));
00162 }
00164 template <class Value>
00165 LEAN_INLINE Value any_cast_checked(volatile any *container)
00166 {
00167     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00168     return any_cast_checked<volatile nonref_value_type&>(const_cast<any*>(container));
00169 }
00171 template <class Value>
00172 LEAN_INLINE Value any_cast_checked(const volatile any *container)
00173 {
00174     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00175     return any_cast_checked<const volatile nonref_value_type&>(const_cast<any*>(container));
00176 }
00177 
00179 template <class Value>
00180 LEAN_INLINE Value any_cast(any &container)
00181 {
00182     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00183     return any_cast_checked<nonref_value_type&>(&container);
00184 }
00186 template <class Value>
00187 LEAN_INLINE Value any_cast(const any &container)
00188 {
00189     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00190     return any_cast<const nonref_value_type&>(const_cast<any&>(container));
00191 }
00193 template <class Value>
00194 LEAN_INLINE Value any_cast(volatile any &container)
00195 {
00196     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00197     return any_cast<volatile nonref_value_type&>(const_cast<any&>(container));
00198 }
00200 template <class Value>
00201 LEAN_INLINE Value any_cast(const volatile any &container)
00202 {
00203     typedef typename lean::strip_reference<Value>::type nonref_value_type;
00204     return any_cast<const volatile nonref_value_type&>(const_cast<any&>(container));
00205 }
00206 
00207 } // namespace
00208 
00209 using containers::any;
00210 using containers::any_value;
00211 
00212 using containers::any_cast;
00213 using containers::any_cast_checked;
00214 
00215 } // namespace
00216 
00217 #ifdef DOXYGEN_READ_THIS
00218 
00219 
00220     #define LEAN_NO_ANY_CAST
00221     #undef LEAN_NO_ANY_CAST
00222 #endif
00223 
00224 #ifndef LEAN_NO_ANY_CAST
00225     using lean::any_cast;
00226     using lean::any_cast_checked;
00227 #endif
00228 
00229 #endif