File indexing completed on 2024-11-15 09:02:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_ANYS_BASIC_ANY_HPP_INCLUDED
0011 #define BOOST_ANYS_BASIC_ANY_HPP_INCLUDED
0012
0013 #include <boost/config.hpp>
0014 #ifdef BOOST_HAS_PRAGMA_ONCE
0015 # pragma once
0016 #endif
0017
0018
0019
0020
0021 #include <boost/any/bad_any_cast.hpp>
0022 #include <boost/any/fwd.hpp>
0023 #include <boost/assert.hpp>
0024 #include <boost/type_index.hpp>
0025 #include <boost/throw_exception.hpp>
0026
0027 #include <memory> // for std::addressof
0028 #include <type_traits>
0029
0030
0031 namespace boost {
0032
0033 namespace anys {
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 template <std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0055 class basic_any
0056 {
0057 static_assert(OptimizeForSize > 0 && OptimizeForAlignment > 0, "Size and Align shall be positive values");
0058 static_assert(OptimizeForSize >= OptimizeForAlignment, "Size shall non less than Align");
0059 static_assert((OptimizeForAlignment & (OptimizeForAlignment - 1)) == 0, "Align shall be a power of 2");
0060 static_assert(OptimizeForSize % OptimizeForAlignment == 0, "Size shall be multiple of alignment");
0061 private:
0062
0063 enum operation
0064 {
0065 Destroy,
0066 Move,
0067 Copy,
0068 AnyCast,
0069 UnsafeCast,
0070 Typeinfo
0071 };
0072
0073 template <typename ValueType>
0074 static void* small_manager(operation op, basic_any& left, const basic_any* right, const boost::typeindex::type_info* info)
0075 {
0076 switch (op)
0077 {
0078 case Destroy:
0079 BOOST_ASSERT(!left.empty());
0080 reinterpret_cast<ValueType*>(&left.content.small_value)->~ValueType();
0081 break;
0082 case Move: {
0083 BOOST_ASSERT(left.empty());
0084 BOOST_ASSERT(right);
0085 BOOST_ASSERT(!right->empty());
0086 BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
0087 ValueType* value = reinterpret_cast<ValueType*>(&const_cast<basic_any*>(right)->content.small_value);
0088 new (&left.content.small_value) ValueType(std::move(*value));
0089 left.man = right->man;
0090 reinterpret_cast<ValueType const*>(&right->content.small_value)->~ValueType();
0091 const_cast<basic_any*>(right)->man = 0;
0092
0093 };
0094 break;
0095
0096 case Copy:
0097 BOOST_ASSERT(left.empty());
0098 BOOST_ASSERT(right);
0099 BOOST_ASSERT(!right->empty());
0100 BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
0101 new (&left.content.small_value) ValueType(*reinterpret_cast<const ValueType*>(&right->content.small_value));
0102 left.man = right->man;
0103 break;
0104 case AnyCast:
0105 BOOST_ASSERT(info);
0106 BOOST_ASSERT(!left.empty());
0107 return boost::typeindex::type_id<ValueType>() == *info ?
0108 reinterpret_cast<typename std::remove_cv<ValueType>::type *>(&left.content.small_value) : 0;
0109 case UnsafeCast:
0110 BOOST_ASSERT(!left.empty());
0111 return reinterpret_cast<typename std::remove_cv<ValueType>::type *>(&left.content.small_value);
0112 case Typeinfo:
0113 return const_cast<void*>(static_cast<const void*>(&boost::typeindex::type_id<ValueType>().type_info()));
0114 }
0115
0116 return 0;
0117 }
0118
0119 template <typename ValueType>
0120 static void* large_manager(operation op, basic_any& left, const basic_any* right, const boost::typeindex::type_info* info)
0121 {
0122 switch (op)
0123 {
0124 case Destroy:
0125 BOOST_ASSERT(!left.empty());
0126 delete static_cast<ValueType*>(left.content.large_value);
0127 break;
0128 case Move:
0129 BOOST_ASSERT(left.empty());
0130 BOOST_ASSERT(right);
0131 BOOST_ASSERT(!right->empty());
0132 BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
0133 left.content.large_value = right->content.large_value;
0134 left.man = right->man;
0135 const_cast<basic_any*>(right)->content.large_value = 0;
0136 const_cast<basic_any*>(right)->man = 0;
0137 break;
0138 case Copy:
0139 BOOST_ASSERT(left.empty());
0140 BOOST_ASSERT(right);
0141 BOOST_ASSERT(!right->empty());
0142 BOOST_ASSERT(right->type() == boost::typeindex::type_id<ValueType>());
0143 left.content.large_value = new ValueType(*static_cast<const ValueType*>(right->content.large_value));
0144 left.man = right->man;
0145 break;
0146 case AnyCast:
0147 BOOST_ASSERT(info);
0148 BOOST_ASSERT(!left.empty());
0149 return boost::typeindex::type_id<ValueType>() == *info ?
0150 static_cast<typename std::remove_cv<ValueType>::type *>(left.content.large_value) : 0;
0151 case UnsafeCast:
0152 BOOST_ASSERT(!left.empty());
0153 return reinterpret_cast<typename std::remove_cv<ValueType>::type *>(left.content.large_value);
0154 case Typeinfo:
0155 return const_cast<void*>(static_cast<const void*>(&boost::typeindex::type_id<ValueType>().type_info()));
0156 }
0157
0158 return 0;
0159 }
0160
0161 template <typename ValueType>
0162 struct is_small_object : std::integral_constant<bool, sizeof(ValueType) <= OptimizeForSize &&
0163 alignof(ValueType) <= OptimizeForAlignment &&
0164 std::is_nothrow_move_constructible<ValueType>::value>
0165 {};
0166
0167 template <typename ValueType>
0168 static void create(basic_any& any, const ValueType& value, std::true_type)
0169 {
0170 typedef typename std::decay<const ValueType>::type DecayedType;
0171
0172 any.man = &small_manager<DecayedType>;
0173 new (&any.content.small_value) ValueType(value);
0174 }
0175
0176 template <typename ValueType>
0177 static void create(basic_any& any, const ValueType& value, std::false_type)
0178 {
0179 typedef typename std::decay<const ValueType>::type DecayedType;
0180
0181 any.man = &large_manager<DecayedType>;
0182 any.content.large_value = new DecayedType(value);
0183 }
0184
0185 template <typename ValueType>
0186 static void create(basic_any& any, ValueType&& value, std::true_type)
0187 {
0188 typedef typename std::decay<const ValueType>::type DecayedType;
0189 any.man = &small_manager<DecayedType>;
0190 new (&any.content.small_value) DecayedType(std::forward<ValueType>(value));
0191 }
0192
0193 template <typename ValueType>
0194 static void create(basic_any& any, ValueType&& value, std::false_type)
0195 {
0196 typedef typename std::decay<const ValueType>::type DecayedType;
0197 any.man = &large_manager<DecayedType>;
0198 any.content.large_value = new DecayedType(std::forward<ValueType>(value));
0199 }
0200
0201
0202 public:
0203 static constexpr std::size_t buffer_size = OptimizeForSize;
0204 static constexpr std::size_t buffer_align = OptimizeForAlignment;
0205
0206 public:
0207
0208
0209 constexpr basic_any() noexcept
0210 : man(0), content()
0211 {
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 template<typename ValueType>
0225 basic_any(const ValueType & value)
0226 : man(0), content()
0227 {
0228 static_assert(
0229 !std::is_same<ValueType, boost::any>::value,
0230 "boost::anys::basic_any shall not be constructed from boost::any"
0231 );
0232 static_assert(
0233 !anys::detail::is_basic_any<ValueType>::value,
0234 "boost::anys::basic_any<A, B> shall not be constructed from boost::anys::basic_any<C, D>"
0235 );
0236 create(*this, value, is_small_object<ValueType>());
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 basic_any(const basic_any & other)
0248 : man(0), content()
0249 {
0250 if (other.man)
0251 {
0252 other.man(Copy, *this, &other, 0);
0253 }
0254 }
0255
0256
0257
0258
0259
0260
0261 basic_any(basic_any&& other) noexcept
0262 : man(0), content()
0263 {
0264 if (other.man)
0265 {
0266 other.man(Move, *this, &other, 0);
0267 }
0268 }
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 template<typename ValueType>
0281 basic_any(ValueType&& value
0282 , typename std::enable_if<!std::is_same<basic_any&, ValueType>::value >::type* = 0
0283 , typename std::enable_if<!std::is_const<ValueType>::value >::type* = 0)
0284 : man(0), content()
0285 {
0286 typedef typename std::decay<ValueType>::type DecayedType;
0287 static_assert(
0288 !std::is_same<DecayedType, boost::any>::value,
0289 "boost::anys::basic_any shall not be constructed from boost::any"
0290 );
0291 static_assert(
0292 !anys::detail::is_basic_any<DecayedType>::value,
0293 "boost::anys::basic_any<A, B> shall not be constructed from boost::anys::basic_any<C, D>"
0294 );
0295 create(*this, static_cast<ValueType&&>(value), is_small_object<DecayedType>());
0296 }
0297
0298
0299
0300
0301 ~basic_any() noexcept
0302 {
0303 if (man)
0304 {
0305 man(Destroy, *this, 0, 0);
0306 }
0307 }
0308
0309 public:
0310
0311
0312
0313
0314
0315 basic_any & swap(basic_any & rhs) noexcept
0316 {
0317 if (this == &rhs)
0318 {
0319 return *this;
0320 }
0321
0322 if (man && rhs.man)
0323 {
0324 basic_any tmp;
0325 rhs.man(Move, tmp, &rhs, 0);
0326 man(Move, rhs, this, 0);
0327 tmp.man(Move, *this, &tmp, 0);
0328 }
0329 else if (man)
0330 {
0331 man(Move, rhs, this, 0);
0332 }
0333 else if (rhs.man)
0334 {
0335 rhs.man(Move, *this, &rhs, 0);
0336 }
0337 return *this;
0338 }
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 basic_any & operator=(const basic_any& rhs)
0350 {
0351 basic_any(rhs).swap(*this);
0352 return *this;
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363 basic_any & operator=(basic_any&& rhs) noexcept
0364 {
0365 rhs.swap(*this);
0366 basic_any().swap(rhs);
0367 return *this;
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 template <class ValueType>
0384 basic_any & operator=(ValueType&& rhs)
0385 {
0386 typedef typename std::decay<ValueType>::type DecayedType;
0387 static_assert(
0388 !std::is_same<DecayedType, boost::any>::value,
0389 "boost::any shall not be assigned into boost::anys::basic_any"
0390 );
0391 static_assert(
0392 !anys::detail::is_basic_any<DecayedType>::value || std::is_same<DecayedType, basic_any>::value,
0393 "boost::anys::basic_any<A, B> shall not be assigned into boost::anys::basic_any<C, D>"
0394 );
0395 basic_any(std::forward<ValueType>(rhs)).swap(*this);
0396 return *this;
0397 }
0398
0399 public:
0400
0401
0402
0403 bool empty() const noexcept
0404 {
0405 return !man;
0406 }
0407
0408
0409 void clear() noexcept
0410 {
0411 basic_any().swap(*this);
0412 }
0413
0414
0415
0416
0417
0418
0419
0420 const boost::typeindex::type_info& type() const BOOST_NOEXCEPT
0421 {
0422 return man
0423 ? *static_cast<const boost::typeindex::type_info*>(man(Typeinfo, const_cast<basic_any&>(*this), 0, 0))
0424 : boost::typeindex::type_id<void>().type_info();
0425 }
0426
0427 private:
0428
0429 template<typename ValueType, std::size_t Size, std::size_t Alignment>
0430 friend ValueType * any_cast(basic_any<Size, Alignment> *) noexcept;
0431
0432 template<typename ValueType, std::size_t Size, std::size_t Alignment>
0433 friend ValueType * unsafe_any_cast(basic_any<Size, Alignment> *) noexcept;
0434
0435 typedef void*(*manager)(operation op, basic_any& left, const basic_any* right, const boost::typeindex::type_info* info);
0436
0437 manager man;
0438
0439 union content {
0440 void * large_value;
0441 alignas(OptimizeForAlignment) unsigned char small_value[OptimizeForSize];
0442 } content;
0443
0444 };
0445
0446
0447
0448 template<std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0449 void swap(basic_any<OptimizeForSize, OptimizeForAlignment>& lhs, basic_any<OptimizeForSize, OptimizeForAlignment>& rhs) noexcept
0450 {
0451 lhs.swap(rhs);
0452 }
0453
0454
0455
0456 template<typename ValueType, std::size_t Size, std::size_t Alignment>
0457 ValueType * any_cast(basic_any<Size, Alignment> * operand) noexcept
0458 {
0459 return operand->man ?
0460 static_cast<typename std::remove_cv<ValueType>::type *>(operand->man(basic_any<Size, Alignment>::AnyCast, *operand, 0, &boost::typeindex::type_id<ValueType>().type_info()))
0461 : 0;
0462 }
0463
0464
0465
0466 template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0467 inline const ValueType * any_cast(const basic_any<OptimizeForSize, OptimizeForAlignment> * operand) noexcept
0468 {
0469 return boost::anys::any_cast<ValueType>(const_cast<basic_any<OptimizeForSize, OptimizeForAlignment> *>(operand));
0470 }
0471
0472
0473
0474
0475 template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0476 ValueType any_cast(basic_any<OptimizeForSize, OptimizeForAlignment> & operand)
0477 {
0478 typedef typename std::remove_reference<ValueType>::type nonref;
0479
0480 nonref * result = boost::anys::any_cast<nonref>(std::addressof(operand));
0481 if(!result)
0482 boost::throw_exception(bad_any_cast());
0483
0484
0485
0486
0487
0488 typedef typename std::conditional<
0489 std::is_reference<ValueType>::value,
0490 ValueType,
0491 typename std::add_lvalue_reference<ValueType>::type
0492 >::type ref_type;
0493
0494 #ifdef BOOST_MSVC
0495 # pragma warning(push)
0496 # pragma warning(disable: 4172)
0497 #endif
0498 return static_cast<ref_type>(*result);
0499 #ifdef BOOST_MSVC
0500 # pragma warning(pop)
0501 #endif
0502 }
0503
0504
0505
0506
0507 template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0508 inline ValueType any_cast(const basic_any<OptimizeForSize, OptimizeForAlignment> & operand)
0509 {
0510 typedef typename std::remove_reference<ValueType>::type nonref;
0511 return boost::anys::any_cast<const nonref &>(const_cast<basic_any<OptimizeForSize, OptimizeForAlignment> &>(operand));
0512 }
0513
0514
0515
0516
0517 template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0518 inline ValueType any_cast(basic_any<OptimizeForSize, OptimizeForAlignment>&& operand)
0519 {
0520 static_assert(
0521 std::is_rvalue_reference<ValueType&&>::value
0522 || std::is_const< typename std::remove_reference<ValueType>::type >::value,
0523 "boost::any_cast shall not be used for getting nonconst references to temporary objects"
0524 );
0525 return boost::anys::any_cast<ValueType>(operand);
0526 }
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536 template<typename ValueType, std::size_t OptimizedForSize, std::size_t OptimizeForAlignment>
0537 inline ValueType * unsafe_any_cast(basic_any<OptimizedForSize, OptimizeForAlignment> * operand) noexcept
0538 {
0539 return static_cast<ValueType*>(operand->man(basic_any<OptimizedForSize, OptimizeForAlignment>::UnsafeCast, *operand, 0, 0));
0540 }
0541
0542 template<typename ValueType, std::size_t OptimizeForSize, std::size_t OptimizeForAlignment>
0543 inline const ValueType * unsafe_any_cast(const basic_any<OptimizeForSize, OptimizeForAlignment> * operand) noexcept
0544 {
0545 return boost::anys::unsafe_any_cast<ValueType>(const_cast<basic_any<OptimizeForSize, OptimizeForAlignment> *>(operand));
0546 }
0547
0548
0549 }
0550
0551 using boost::anys::any_cast;
0552 using boost::anys::unsafe_any_cast;
0553
0554 }
0555
0556 #endif