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 - 2019 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/type_traits/conditional.hpp> 34 35 namespace boost 36 { 37 class any 38 { 39 public: // structors 40 any()41 BOOST_CONSTEXPR 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 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 assignment 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 BOOST_SYMBOL_VISIBLE 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 170 #ifndef BOOST_NO_CXX11_FINAL 171 final 172 #endif 173 : public placeholder 174 { 175 public: // structors 176 holder(const ValueType & value)177 holder(const ValueType & value) 178 : held(value) 179 { 180 } 181 182 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES holder(ValueType && value)183 holder(ValueType&& value) 184 : held(static_cast< ValueType&& >(value)) 185 { 186 } 187 #endif 188 public: // queries 189 type() const190 virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT 191 { 192 return boost::typeindex::type_id<ValueType>().type_info(); 193 } 194 clone() const195 virtual placeholder * clone() const 196 { 197 return new holder(held); 198 } 199 200 public: // representation 201 202 ValueType held; 203 204 private: // intentionally left unimplemented 205 holder & operator=(const holder &); 206 }; 207 208 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 209 210 private: // representation 211 212 template<typename ValueType> 213 friend ValueType * any_cast(any *) BOOST_NOEXCEPT; 214 215 template<typename ValueType> 216 friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT; 217 218 #else 219 220 public: // representation (public so any_cast can be non-friend) 221 222 #endif 223 224 placeholder * content; 225 226 }; 227 swap(any & lhs,any & rhs)228 inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT 229 { 230 lhs.swap(rhs); 231 } 232 233 class BOOST_SYMBOL_VISIBLE bad_any_cast : 234 #ifndef BOOST_NO_RTTI 235 public std::bad_cast 236 #else 237 public std::exception 238 #endif 239 { 240 public: what() const241 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW 242 { 243 return "boost::bad_any_cast: " 244 "failed conversion using boost::any_cast"; 245 } 246 }; 247 248 template<typename ValueType> any_cast(any * operand)249 ValueType * any_cast(any * operand) BOOST_NOEXCEPT 250 { 251 return operand && operand->type() == boost::typeindex::type_id<ValueType>() 252 ? boost::addressof( 253 static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held 254 ) 255 : 0; 256 } 257 258 template<typename ValueType> any_cast(const any * operand)259 inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT 260 { 261 return any_cast<ValueType>(const_cast<any *>(operand)); 262 } 263 264 template<typename ValueType> any_cast(any & operand)265 ValueType any_cast(any & operand) 266 { 267 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; 268 269 270 nonref * result = any_cast<nonref>(boost::addressof(operand)); 271 if(!result) 272 boost::throw_exception(bad_any_cast()); 273 274 // Attempt to avoid construction of a temporary object in cases when 275 // `ValueType` is not a reference. Example: 276 // `static_cast<std::string>(*result);` 277 // which is equal to `std::string(*result);` 278 typedef BOOST_DEDUCED_TYPENAME boost::conditional< 279 boost::is_reference<ValueType>::value, 280 ValueType, 281 BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type 282 >::type ref_type; 283 284 #ifdef BOOST_MSVC 285 # pragma warning(push) 286 # pragma warning(disable: 4172) // "returning address of local variable or temporary" but *result is not local! 287 #endif 288 return static_cast<ref_type>(*result); 289 #ifdef BOOST_MSVC 290 # pragma warning(pop) 291 #endif 292 } 293 294 template<typename ValueType> any_cast(const any & operand)295 inline ValueType any_cast(const any & operand) 296 { 297 typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; 298 return any_cast<const nonref &>(const_cast<any &>(operand)); 299 } 300 301 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 302 template<typename ValueType> any_cast(any && operand)303 inline ValueType any_cast(any&& operand) 304 { 305 BOOST_STATIC_ASSERT_MSG( 306 boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/ 307 || boost::is_const< typename boost::remove_reference<ValueType>::type >::value, 308 "boost::any_cast shall not be used for getting nonconst references to temporary objects" 309 ); 310 return any_cast<ValueType>(operand); 311 } 312 #endif 313 314 315 // Note: The "unsafe" versions of any_cast are not part of the 316 // public interface and may be removed at any time. They are 317 // required where we know what type is stored in the any and can't 318 // use typeid() comparison, e.g., when our types may travel across 319 // different shared libraries. 320 template<typename ValueType> unsafe_any_cast(any * operand)321 inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT 322 { 323 return boost::addressof( 324 static_cast<any::holder<ValueType> *>(operand->content)->held 325 ); 326 } 327 328 template<typename ValueType> unsafe_any_cast(const any * operand)329 inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT 330 { 331 return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); 332 } 333 } 334 335 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. 336 // Copyright Antony Polukhin, 2013-2019. 337 // 338 // Distributed under the Boost Software License, Version 1.0. (See 339 // accompanying file LICENSE_1_0.txt or copy at 340 // http://www.boost.org/LICENSE_1_0.txt) 341 342 #endif 343