lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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