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