1 // See http://www.boost.org/libs/any for Documentation. 2 3 #ifndef BOOST_ANY_INCLUDED 4 #define BOOST_ANY_INCLUDED 5 6 #if defined(_MSC_VER) 7 # pragma once 8 #endif 9 10 // what: variant type boost::any 11 // who: contributed by Kevlin Henney, 12 // with features contributed and bugs found by 13 // Antony Polukhin, Ed Brey, Mark Rodgers, 14 // Peter Dimov, and James Curran 15 // when: July 2001, April 2013 - May 2013 16 17 #include <algorithm> 18 19 #include <boost/config.hpp> 20 #include <boost/type_index.hpp> 21 #include <boost/type_traits/remove_reference.hpp> 22 #include <boost/type_traits/decay.hpp> 23 #include <boost/type_traits/remove_cv.hpp> 24 #include <boost/type_traits/add_reference.hpp> 25 #include <boost/type_traits/is_reference.hpp> 26 #include <boost/type_traits/is_const.hpp> 27 #include <boost/throw_exception.hpp> 28 #include <boost/static_assert.hpp> 29 #include <boost/utility/enable_if.hpp> 30 #include <boost/core/addressof.hpp> 31 #include <boost/type_traits/is_same.hpp> 32 #include <boost/type_traits/is_const.hpp> 33 #include <boost/mpl/if.hpp> 34 35 namespace boost 36 { 37 class any 38 { 39 public: // structors 40 any()41 any() BOOST_NOEXCEPT 42 : content(0) 43 { 44 } 45 46 template<typename ValueType> any(const ValueType & value)47 any(const ValueType & value) 48 : content(new holder< 49 BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type 50 >(value)) 51 { 52 } 53 any(const any & other)54 any(const any & other) 55 : content(other.content ? other.content->clone() : 0) 56 { 57 } 58 59 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 60 // Move constructor any(any && other)61 any(any&& other) BOOST_NOEXCEPT 62 : content(other.content) 63 { 64 other.content = 0; 65 } 66 67 // Perfect forwarding of ValueType 68 template<typename ValueType> any(ValueType && value,typename boost::disable_if<boost::is_same<any &,ValueType>>::type * =0,typename boost::disable_if<boost::is_const<ValueType>>::type * =0)69 any(ValueType&& value 70 , typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&` 71 , typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&` 72 : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value))) 73 { 74 } 75 #endif 76 ~any()77 ~any() BOOST_NOEXCEPT 78 { 79 delete content; 80 } 81 82 public: // modifiers 83 swap(any & rhs)84 any & swap(any & rhs) BOOST_NOEXCEPT 85 { 86 std::swap(content, rhs.content); 87 return *this; 88 } 89 90 91 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES 92 template<typename ValueType> operator =(const ValueType & rhs)93 any & operator=(const ValueType & rhs) 94 { 95 any(rhs).swap(*this); 96 return *this; 97 } 98 operator =(any rhs)99 any & operator=(any rhs) 100 { 101 any(rhs).swap(*this); 102 return *this; 103 } 104 105 #else operator =(const any & rhs)106 any & operator=(const any& rhs) 107 { 108 any(rhs).swap(*this); 109 return *this; 110 } 111 112 // move assignement operator =(any && rhs)113 any & operator=(any&& rhs) BOOST_NOEXCEPT 114 { 115 rhs.swap(*this); 116 any().swap(rhs); 117 return *this; 118 } 119 120 // Perfect forwarding of ValueType 121 template <class ValueType> operator =(ValueType && rhs)122 any & operator=(ValueType&& rhs) 123 { 124 any(static_cast<ValueType&&>(rhs)).swap(*this); 125 return *this; 126 } 127 #endif 128 129 public: // queries 130 empty() const131 bool empty() const BOOST_NOEXCEPT 132 { 133 return !content; 134 } 135 clear()136 void clear() BOOST_NOEXCEPT 137 { 138 any().swap(*this); 139 } 140 type() const141 const boost::typeindex::type_info& type() const BOOST_NOEXCEPT 142 { 143 return content ? content->type() : boost::typeindex::type_id<void>().type_info(); 144 } 145 146 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 147 private: // types 148 #else 149 public: // types (public so any_cast can be non-friend) 150 #endif 151 152 class placeholder 153 { 154 public: // structors 155 ~placeholder()156 virtual ~placeholder() 157 { 158 } 159 160 public: // queries 161 162 virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0; 163 164 virtual placeholder * clone() const = 0; 165 166 }; 167 168 template<typename ValueType> 169 class holder : public placeholder 170 { 171 public: // structors 172 holder(const ValueType & value)173 holder(const ValueType & value) 174 : held(value) 175 { 176 } 177 178 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES holder(ValueType && value)179 holder(ValueType&& value) 180 : held(static_cast< ValueType&& >(value)) 181 { 182 } 183 #endif 184 public: // queries 185 type() const186 virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT 187 { 188 return boost::typeindex::type_id<ValueType>().type_info(); 189 } 190 clone() const191 virtual placeholder * clone() const 192 { 193 return new holder(held); 194 } 195 196 public: // representation 197 198 ValueType held; 199 200 private: // intentionally left unimplemented 201 holder & operator=(const holder &); 202 }; 203 204 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 205 206 private: // representation 207 208 template<typename ValueType> 209 friend ValueType * any_cast(any *) BOOST_NOEXCEPT; 210 211 template<typename ValueType> 212 friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT; 213 214 #else 215 216 public: // representation (public so any_cast can be non-friend) 217 218 #endif 219 220 placeholder * content; 221 222 }; 223 swap(any & lhs,any & rhs)224 inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT 225 { 226 lhs.swap(rhs); 227 } 228 229 class BOOST_SYMBOL_VISIBLE bad_any_cast : 230 #ifndef BOOST_NO_RTTI 231 public std::bad_cast 232 #else 233 public std::exception 234 #endif 235 { 236 public: what() const237 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW 238 { 239 return "boost::bad_any_cast: " 240 "failed conversion using boost::any_cast"; 241 } 242 }; 243 244 template<typename ValueType> any_cast(any * operand)245 ValueType * any_cast(any * operand) BOOST_NOEXCEPT 246 { 247 return operand && operand->type() == boost::typeindex::type_id<ValueType>() 248 ? boost::addressof( 249 static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held 250 ) 251 : 0; 252 } 253 254 template<typename ValueType> any_cast(const any * operand)255 inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT 256 { 257 return any_cast<ValueType>(const_cast<any *>(operand)); 258 } 259 260 template<typename ValueType> any_cast(any & operand)261 ValueType any_cast(any & operand) 262 { 263 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; 264 265 266 nonref * result = any_cast<nonref>(boost::addressof(operand)); 267 if(!result) 268 boost::throw_exception(bad_any_cast()); 269 270 // Attempt to avoid construction of a temporary object in cases when 271 // `ValueType` is not a reference. Example: 272 // `static_cast<std::string>(*result);` 273 // which is equal to `std::string(*result);` 274 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< 275 boost::is_reference<ValueType>, 276 ValueType, 277 BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type 278 >::type ref_type; 279 280 #ifdef BOOST_MSVC 281 # pragma warning(push) 282 # pragma warning(disable: 4172) // "returning address of local variable or temporary" but *result is not local! 283 #endif 284 return static_cast<ref_type>(*result); 285 #ifdef BOOST_MSVC 286 # pragma warning(pop) 287 #endif 288 } 289 290 template<typename ValueType> any_cast(const any & operand)291 inline ValueType any_cast(const any & operand) 292 { 293 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; 294 return any_cast<const nonref &>(const_cast<any &>(operand)); 295 } 296 297 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 298 template<typename ValueType> any_cast(any && operand)299 inline ValueType any_cast(any&& operand) 300 { 301 BOOST_STATIC_ASSERT_MSG( 302 boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/ 303 || boost::is_const< typename boost::remove_reference<ValueType>::type >::value, 304 "boost::any_cast shall not be used for getting nonconst references to temporary objects" 305 ); 306 return any_cast<ValueType>(operand); 307 } 308 #endif 309 310 311 // Note: The "unsafe" versions of any_cast are not part of the 312 // public interface and may be removed at any time. They are 313 // required where we know what type is stored in the any and can't 314 // use typeid() comparison, e.g., when our types may travel across 315 // different shared libraries. 316 template<typename ValueType> unsafe_any_cast(any * operand)317 inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT 318 { 319 return boost::addressof( 320 static_cast<any::holder<ValueType> *>(operand->content)->held 321 ); 322 } 323 324 template<typename ValueType> unsafe_any_cast(const any * operand)325 inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT 326 { 327 return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); 328 } 329 } 330 331 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. 332 // 333 // Distributed under the Boost Software License, Version 1.0. (See 334 // accompanying file LICENSE_1_0.txt or copy at 335 // http://www.boost.org/LICENSE_1_0.txt) 336 337 #endif 338