Line data Source code
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 : 41 1070 : BOOST_CONSTEXPR any() BOOST_NOEXCEPT 42 1070 : : content(0) 43 : { 44 : } 45 : 46 : template<typename ValueType> 47 1445 : any(const ValueType & value) 48 1445 : : content(new holder< 49 : BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type 50 1445 : >(value)) 51 : { 52 : } 53 : 54 7829 : any(const any & other) 55 7829 : : content(other.content ? other.content->clone() : 0) 56 : { 57 : } 58 : 59 : #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 60 : // Move constructor 61 8 : any(any&& other) BOOST_NOEXCEPT 62 8 : : content(other.content) 63 : { 64 8 : other.content = 0; 65 : } 66 : 67 : // Perfect forwarding of ValueType 68 : template<typename ValueType> 69 6392 : 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 6392 : : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value))) 73 : { 74 712 : } 75 : #endif 76 : 77 7853 : ~any() BOOST_NOEXCEPT 78 8 : { 79 7853 : delete content; 80 8 : } 81 : 82 : public: // modifiers 83 : 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> 93 : any & operator=(const ValueType & rhs) 94 : { 95 : any(rhs).swap(*this); 96 : return *this; 97 : } 98 : 99 : any & operator=(any rhs) 100 : { 101 : rhs.swap(*this); 102 : return *this; 103 : } 104 : 105 : #else 106 : any & operator=(const any& rhs) 107 : { 108 : any(rhs).swap(*this); 109 : return *this; 110 : } 111 : 112 : // move assignment 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> 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 : 131 0 : bool empty() const BOOST_NOEXCEPT 132 : { 133 0 : return !content; 134 : } 135 : 136 : void clear() BOOST_NOEXCEPT 137 : { 138 : any().swap(*this); 139 : } 140 : 141 17 : const boost::typeindex::type_info& type() const BOOST_NOEXCEPT 142 : { 143 17 : 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 38755 : class BOOST_SYMBOL_VISIBLE placeholder 153 : { 154 : public: // structors 155 : 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 : 177 33075 : holder(const ValueType & value) 178 2157 : : held(value) 179 : { 180 5696 : } 181 : 182 : #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 183 5680 : holder(ValueType&& value) 184 5680 : : held(static_cast< ValueType&& >(value)) 185 : { 186 : } 187 : #endif 188 : public: // queries 189 : 190 16 : virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT 191 : { 192 16 : return boost::typeindex::type_id<ValueType>().type_info(); 193 : } 194 : 195 30918 : virtual placeholder * clone() const 196 : { 197 35902 : 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 : 228 : inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT 229 : { 230 : lhs.swap(rhs); 231 : } 232 : 233 0 : 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: 241 0 : virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW 242 : { 243 0 : return "boost::bad_any_cast: " 244 0 : "failed conversion using boost::any_cast"; 245 : } 246 : }; 247 : 248 : template<typename ValueType> 249 16 : ValueType * any_cast(any * operand) BOOST_NOEXCEPT 250 : { 251 32 : return operand && operand->type() == boost::typeindex::type_id<ValueType>() 252 32 : ? boost::addressof( 253 16 : static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held 254 : ) 255 16 : : 0; 256 : } 257 : 258 : template<typename ValueType> 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> 265 16 : ValueType any_cast(any & operand) 266 : { 267 : typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; 268 : 269 : 270 16 : nonref * result = any_cast<nonref>(boost::addressof(operand)); 271 16 : if(!result) 272 0 : 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 16 : return static_cast<ref_type>(*result); 289 : #ifdef BOOST_MSVC 290 : # pragma warning(pop) 291 : #endif 292 : } 293 : 294 : template<typename ValueType> 295 16 : inline ValueType any_cast(const any & operand) 296 : { 297 : typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; 298 16 : return any_cast<const nonref &>(const_cast<any &>(operand)); 299 : } 300 : 301 : #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 302 : template<typename ValueType> 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> 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> 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