annotate DEPENDENCIES/generic/include/boost/variant/variant.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //-----------------------------------------------------------------------------
Chris@16 2 // boost variant/variant.hpp header file
Chris@16 3 // See http://www.boost.org for updates, documentation, and revision history.
Chris@16 4 //-----------------------------------------------------------------------------
Chris@16 5 //
Chris@16 6 // Copyright (c) 2002-2003 Eric Friedman, Itay Maman
Chris@101 7 // Copyright (c) 2012-2014 Antony Polukhin
Chris@16 8 //
Chris@16 9 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 10 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 11 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 12
Chris@16 13 // Thanks to Adam Romanek for providing patches for exception-disabled env.
Chris@16 14
Chris@16 15 #ifndef BOOST_VARIANT_VARIANT_HPP
Chris@16 16 #define BOOST_VARIANT_VARIANT_HPP
Chris@16 17
Chris@16 18 #include <cstddef> // for std::size_t
Chris@16 19 #include <new> // for placement new
Chris@16 20
Chris@101 21 #include "boost/type_index.hpp"
Chris@16 22
Chris@16 23 #include "boost/variant/detail/config.hpp"
Chris@16 24 #include "boost/mpl/aux_/value_wknd.hpp"
Chris@16 25
Chris@16 26 #include "boost/variant/variant_fwd.hpp"
Chris@16 27 #include "boost/variant/detail/backup_holder.hpp"
Chris@16 28 #include "boost/variant/detail/enable_recursive_fwd.hpp"
Chris@16 29 #include "boost/variant/detail/forced_return.hpp"
Chris@16 30 #include "boost/variant/detail/initializer.hpp"
Chris@16 31 #include "boost/variant/detail/make_variant_list.hpp"
Chris@16 32 #include "boost/variant/detail/over_sequence.hpp"
Chris@16 33 #include "boost/variant/detail/visitation_impl.hpp"
Chris@16 34 #include "boost/variant/detail/hash_variant.hpp"
Chris@16 35
Chris@16 36 #include "boost/variant/detail/generic_result_type.hpp"
Chris@16 37 #include "boost/variant/detail/move.hpp"
Chris@16 38
Chris@16 39 #include "boost/detail/no_exceptions_support.hpp"
Chris@16 40 #include "boost/detail/reference_content.hpp"
Chris@16 41 #include "boost/aligned_storage.hpp"
Chris@16 42 #include "boost/blank.hpp"
Chris@16 43 #include "boost/math/common_factor_ct.hpp"
Chris@16 44 #include "boost/static_assert.hpp"
Chris@16 45 #include "boost/preprocessor/cat.hpp"
Chris@16 46 #include "boost/preprocessor/repeat.hpp"
Chris@16 47 #include "boost/type_traits/alignment_of.hpp"
Chris@16 48 #include "boost/type_traits/add_const.hpp"
Chris@16 49 #include "boost/type_traits/has_nothrow_constructor.hpp"
Chris@16 50 #include "boost/type_traits/has_nothrow_copy.hpp"
Chris@101 51 #include "boost/type_traits/is_nothrow_move_assignable.hpp"
Chris@16 52 #include "boost/type_traits/is_nothrow_move_constructible.hpp"
Chris@16 53 #include "boost/type_traits/is_const.hpp"
Chris@16 54 #include "boost/type_traits/is_same.hpp"
Chris@16 55 #include "boost/type_traits/is_rvalue_reference.hpp"
Chris@16 56 #include "boost/utility/enable_if.hpp"
Chris@16 57 #include "boost/utility/declval.hpp"
Chris@16 58 #include "boost/variant/recursive_wrapper_fwd.hpp"
Chris@16 59 #include "boost/variant/static_visitor.hpp"
Chris@16 60
Chris@16 61 #include "boost/mpl/assert.hpp"
Chris@16 62 #include "boost/mpl/begin_end.hpp"
Chris@16 63 #include "boost/mpl/bool.hpp"
Chris@16 64 #include "boost/mpl/deref.hpp"
Chris@16 65 #include "boost/mpl/empty.hpp"
Chris@16 66 #include "boost/mpl/eval_if.hpp"
Chris@16 67 #include "boost/mpl/find_if.hpp"
Chris@16 68 #include "boost/mpl/fold.hpp"
Chris@16 69 #include "boost/mpl/front.hpp"
Chris@16 70 #include "boost/mpl/identity.hpp"
Chris@16 71 #include "boost/mpl/if.hpp"
Chris@16 72 #include "boost/mpl/int.hpp"
Chris@16 73 #include "boost/mpl/is_sequence.hpp"
Chris@16 74 #include "boost/mpl/iterator_range.hpp"
Chris@16 75 #include "boost/mpl/iter_fold_if.hpp"
Chris@16 76 #include "boost/mpl/logical.hpp"
Chris@16 77 #include "boost/mpl/max_element.hpp"
Chris@16 78 #include "boost/mpl/next.hpp"
Chris@16 79 #include "boost/mpl/not.hpp"
Chris@16 80 #include "boost/mpl/pair.hpp"
Chris@16 81 #include "boost/mpl/protect.hpp"
Chris@16 82 #include "boost/mpl/push_front.hpp"
Chris@16 83 #include "boost/mpl/same_as.hpp"
Chris@16 84 #include "boost/mpl/size_t.hpp"
Chris@16 85 #include "boost/mpl/sizeof.hpp"
Chris@16 86 #include "boost/mpl/transform.hpp"
Chris@16 87
Chris@16 88 ///////////////////////////////////////////////////////////////////////////////
Chris@16 89 // Implementation Macros:
Chris@16 90 //
Chris@16 91 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
Chris@16 92 // Defined in boost/variant/detail/visitation_impl.hpp.
Chris@16 93 //
Chris@16 94 // BOOST_VARIANT_MINIMIZE_SIZE
Chris@16 95 // When #defined, implementation employs all known means to minimize the
Chris@16 96 // size of variant obje cts. However, often unsuccessful due to alignment
Chris@16 97 // issues, and potentially harmful to runtime speed, so not enabled by
Chris@16 98 // default. (TODO: Investigate further.)
Chris@16 99
Chris@16 100 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
Chris@16 101 # include <climits> // for SCHAR_MAX
Chris@16 102 # include "boost/mpl/eval_if.hpp"
Chris@16 103 # include "boost/mpl/equal_to.hpp"
Chris@16 104 # include "boost/mpl/identity.hpp"
Chris@16 105 # include "boost/mpl/int.hpp"
Chris@16 106 # include "boost/mpl/if.hpp"
Chris@16 107 # include "boost/mpl/less.hpp"
Chris@16 108 # include "boost/mpl/long.hpp"
Chris@16 109 # include "boost/mpl/O1_size.hpp"
Chris@16 110 #endif
Chris@16 111
Chris@16 112
Chris@16 113 namespace boost {
Chris@16 114
Chris@16 115 namespace detail { namespace variant {
Chris@16 116
Chris@16 117 ///////////////////////////////////////////////////////////////////////////////
Chris@16 118 // (detail) metafunction max_value
Chris@16 119 //
Chris@16 120 // Finds the maximum value of the unary metafunction F over Sequence.
Chris@16 121 //
Chris@16 122 template <typename Sequence, typename F>
Chris@16 123 struct max_value
Chris@16 124 {
Chris@16 125 private: // helpers, for metafunction result (below)
Chris@16 126
Chris@16 127 typedef typename mpl::transform1<Sequence, F>::type transformed_;
Chris@16 128 typedef typename mpl::max_element<transformed_
Chris@16 129
Chris@16 130 >::type max_it;
Chris@16 131
Chris@16 132 public: // metafunction result
Chris@16 133
Chris@16 134 typedef typename mpl::deref<max_it>::type
Chris@16 135 type;
Chris@16 136
Chris@16 137 };
Chris@16 138
Chris@16 139 struct add_alignment
Chris@16 140 {
Chris@16 141 template <typename State, typename Item>
Chris@16 142 struct apply
Chris@16 143 : mpl::size_t<
Chris@16 144 ::boost::math::static_lcm<
Chris@16 145 BOOST_MPL_AUX_VALUE_WKND(State)::value
Chris@16 146 , ::boost::alignment_of<Item>::value
Chris@16 147 >::value
Chris@16 148 >
Chris@16 149 {};
Chris@16 150 };
Chris@16 151
Chris@16 152 ///////////////////////////////////////////////////////////////////////////////
Chris@16 153 // (detail) metafunction find_fallback_type
Chris@16 154 //
Chris@16 155 // Provides a fallback (i.e., nothrow default-constructible) type from the
Chris@16 156 // specified sequence, or no_fallback_type if not found.
Chris@16 157 //
Chris@16 158 // This implementation is designed to prefer boost::blank over other potential
Chris@16 159 // fallback types, regardless of its position in the specified sequence.
Chris@16 160 //
Chris@16 161
Chris@16 162 class no_fallback_type;
Chris@16 163
Chris@16 164 struct find_fallback_type_pred
Chris@16 165 {
Chris@16 166 template <typename Iterator>
Chris@16 167 struct apply
Chris@16 168 {
Chris@16 169 private:
Chris@16 170 typedef typename mpl::deref<Iterator>::type t_;
Chris@16 171
Chris@16 172 public:
Chris@16 173 typedef mpl::not_< has_nothrow_constructor<t_> > type;
Chris@16 174 };
Chris@16 175 };
Chris@16 176
Chris@16 177 template <typename Types>
Chris@16 178 struct find_fallback_type
Chris@16 179 {
Chris@16 180 private: // helpers, for metafunction result (below)
Chris@16 181
Chris@16 182 typedef typename mpl::end<Types>::type end_it;
Chris@16 183
Chris@16 184 // [Find the first suitable fallback type...]
Chris@16 185
Chris@16 186 typedef typename mpl::iter_fold_if<
Chris@16 187 Types
Chris@16 188 , mpl::int_<0>, mpl::protect< mpl::next<> >
Chris@16 189 , mpl::protect< find_fallback_type_pred >
Chris@16 190 >::type first_result_;
Chris@16 191
Chris@16 192 typedef typename first_result_::first first_result_index;
Chris@16 193 typedef typename first_result_::second first_result_it;
Chris@16 194
Chris@16 195 // [...now search the rest of the sequence for boost::blank...]
Chris@16 196
Chris@16 197 typedef typename mpl::iter_fold_if<
Chris@16 198 mpl::iterator_range< first_result_it,end_it >
Chris@16 199 , first_result_index, mpl::protect< mpl::next<> >
Chris@16 200 , mpl::protect< mpl::not_same_as<boost::blank> >
Chris@16 201 >::type second_result_;
Chris@16 202
Chris@16 203 typedef typename second_result_::second second_result_it;
Chris@16 204
Chris@16 205 public: // metafunction result
Chris@16 206
Chris@16 207 // [...and return the results of the search:]
Chris@16 208 typedef typename mpl::eval_if<
Chris@16 209 is_same< second_result_it,end_it >
Chris@16 210 , mpl::if_<
Chris@16 211 is_same< first_result_it,end_it >
Chris@16 212 , mpl::pair< no_fallback_type,no_fallback_type >
Chris@16 213 , first_result_
Chris@16 214 >
Chris@16 215 , mpl::identity< second_result_ >
Chris@16 216 >::type type;
Chris@16 217
Chris@16 218 };
Chris@16 219
Chris@16 220 #ifndef BOOST_NO_CXX11_NOEXCEPT
Chris@16 221 ///////////////////////////////////////////////////////////////////////////////
Chris@101 222 // (detail) metafunction is_variant_move_noexcept_constructible
Chris@16 223 //
Chris@16 224 // Returns true_type if all the types are nothrow move constructible.
Chris@16 225 //
Chris@16 226 template <class Types>
Chris@101 227 struct is_variant_move_noexcept_constructible {
Chris@16 228 typedef typename boost::mpl::find_if<
Chris@16 229 Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
Chris@16 230 >::type iterator_t;
Chris@16 231
Chris@16 232 typedef typename boost::mpl::end<Types>::type end_t;
Chris@16 233 typedef typename boost::is_same<
Chris@16 234 iterator_t, end_t
Chris@16 235 >::type type;
Chris@16 236 };
Chris@101 237
Chris@101 238 ///////////////////////////////////////////////////////////////////////////////
Chris@101 239 // (detail) metafunction is_variant_move_noexcept_assignable
Chris@101 240 //
Chris@101 241 // Returns true_type if all the types are nothrow move constructible.
Chris@101 242 //
Chris@101 243 template <class Types>
Chris@101 244 struct is_variant_move_noexcept_assignable {
Chris@101 245 typedef typename boost::mpl::find_if<
Chris@101 246 Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
Chris@101 247 >::type iterator_t;
Chris@101 248
Chris@101 249 typedef typename boost::mpl::end<Types>::type end_t;
Chris@101 250 typedef typename boost::is_same<
Chris@101 251 iterator_t, end_t
Chris@101 252 >::type type;
Chris@101 253 };
Chris@16 254 #endif // BOOST_NO_CXX11_NOEXCEPT
Chris@16 255
Chris@16 256 ///////////////////////////////////////////////////////////////////////////////
Chris@16 257 // (detail) metafunction make_storage
Chris@16 258 //
Chris@16 259 // Provides an aligned storage type capable of holding any of the types
Chris@16 260 // specified in the given type-sequence.
Chris@16 261 //
Chris@16 262
Chris@16 263 template <typename Types, typename NeverUsesBackupFlag>
Chris@16 264 struct make_storage
Chris@16 265 {
Chris@16 266 private: // helpers, for metafunction result (below)
Chris@16 267
Chris@16 268 typedef typename mpl::eval_if<
Chris@16 269 NeverUsesBackupFlag
Chris@16 270 , mpl::identity< Types >
Chris@16 271 , mpl::push_front<
Chris@16 272 Types, backup_holder<void*>
Chris@16 273 >
Chris@16 274 >::type types;
Chris@16 275
Chris@16 276 typedef typename max_value<
Chris@16 277 types, mpl::sizeof_<mpl::_1>
Chris@16 278 >::type max_size;
Chris@16 279
Chris@16 280 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
Chris@16 281
Chris@16 282 typedef typename mpl::fold<
Chris@16 283 types
Chris@16 284 , mpl::size_t<1>
Chris@16 285 , add_alignment
Chris@16 286 >::type max_alignment;
Chris@16 287
Chris@16 288 #else // borland
Chris@16 289
Chris@16 290 // temporary workaround -- use maximal alignment
Chris@16 291 typedef mpl::size_t< -1 > max_alignment;
Chris@16 292
Chris@16 293 #endif // borland workaround
Chris@16 294
Chris@16 295 public: // metafunction result
Chris@16 296
Chris@16 297 typedef ::boost::aligned_storage<
Chris@16 298 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
Chris@16 299 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
Chris@16 300 > type;
Chris@16 301 };
Chris@16 302
Chris@16 303 ///////////////////////////////////////////////////////////////////////////////
Chris@16 304 // (detail) class destroyer
Chris@16 305 //
Chris@16 306 // Internal visitor that destroys the value it visits.
Chris@16 307 //
Chris@16 308 struct destroyer
Chris@16 309 : public static_visitor<>
Chris@16 310 {
Chris@16 311 public: // visitor interfaces
Chris@16 312
Chris@16 313 template <typename T>
Chris@16 314 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@101 315 internal_visit(T& operand, int) const BOOST_NOEXCEPT
Chris@16 316 {
Chris@101 317 operand.~T(); // must be noexcept
Chris@16 318
Chris@16 319 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
Chris@16 320 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 321 operand; // suppresses warnings
Chris@16 322 #endif
Chris@16 323
Chris@16 324 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 325 }
Chris@16 326
Chris@16 327 };
Chris@16 328
Chris@16 329 ///////////////////////////////////////////////////////////////////////////////
Chris@16 330 // (detail) class template known_get
Chris@16 331 //
Chris@16 332 // Visitor that returns a reference to content of the specified type.
Chris@16 333 //
Chris@16 334 // Precondition: visited variant MUST contain logical content of type T.
Chris@16 335 //
Chris@16 336 template <typename T>
Chris@16 337 class known_get
Chris@16 338 : public static_visitor<T&>
Chris@16 339 {
Chris@16 340
Chris@16 341 public: // visitor interface
Chris@16 342
Chris@16 343 T& operator()(T& operand) const BOOST_NOEXCEPT
Chris@16 344 {
Chris@16 345 return operand;
Chris@16 346 }
Chris@16 347
Chris@16 348 template <typename U>
Chris@16 349 T& operator()(U&) const
Chris@16 350 {
Chris@16 351 // logical error to be here: see precondition above
Chris@16 352 return ::boost::detail::variant::forced_return< T& >();
Chris@16 353 }
Chris@16 354 };
Chris@16 355
Chris@16 356 ///////////////////////////////////////////////////////////////////////////////
Chris@16 357 // (detail) class copy_into
Chris@16 358 //
Chris@16 359 // Internal visitor that copies the value it visits into the given buffer.
Chris@16 360 //
Chris@16 361 class copy_into
Chris@16 362 : public static_visitor<>
Chris@16 363 {
Chris@16 364 private: // representation
Chris@16 365
Chris@16 366 void* storage_;
Chris@16 367
Chris@16 368 public: // structors
Chris@16 369
Chris@16 370 explicit copy_into(void* storage) BOOST_NOEXCEPT
Chris@16 371 : storage_(storage)
Chris@16 372 {
Chris@16 373 }
Chris@16 374
Chris@16 375 public: // internal visitor interface
Chris@16 376
Chris@16 377 template <typename T>
Chris@16 378 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 379 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 380 {
Chris@16 381 new(storage_) T( operand.get() );
Chris@16 382 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 383 }
Chris@16 384
Chris@16 385 template <typename T>
Chris@16 386 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 387 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 388 {
Chris@16 389 new(storage_) T( operand.get() );
Chris@16 390 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 391 }
Chris@16 392
Chris@16 393 template <typename T>
Chris@16 394 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 395 internal_visit(const T& operand, int) const
Chris@16 396 {
Chris@16 397 new(storage_) T(operand);
Chris@16 398 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 399 }
Chris@16 400
Chris@16 401 };
Chris@16 402
Chris@16 403 ///////////////////////////////////////////////////////////////////////////////
Chris@16 404 // (detail) class move_into
Chris@16 405 //
Chris@16 406 // Internal visitor that moves the value it visits into the given buffer.
Chris@16 407 //
Chris@16 408 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 409 class move_into
Chris@16 410 : public static_visitor<>
Chris@16 411 {
Chris@16 412 private: // representation
Chris@16 413
Chris@16 414 void* storage_;
Chris@16 415
Chris@16 416 public: // structors
Chris@16 417
Chris@16 418 explicit move_into(void* storage) BOOST_NOEXCEPT
Chris@16 419 : storage_(storage)
Chris@16 420 {
Chris@16 421 }
Chris@16 422
Chris@16 423 public: // internal visitor interface
Chris@16 424
Chris@16 425 template <typename T>
Chris@16 426 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 427 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 428 {
Chris@16 429 new(storage_) T( ::boost::detail::variant::move(operand.get()) );
Chris@16 430 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 431 }
Chris@16 432
Chris@16 433 template <typename T>
Chris@16 434 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 435 internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
Chris@16 436 {
Chris@16 437 new(storage_) T(::boost::detail::variant::move(operand));
Chris@16 438 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 439 }
Chris@16 440 };
Chris@16 441 #endif
Chris@16 442
Chris@16 443 ///////////////////////////////////////////////////////////////////////////////
Chris@16 444 // (detail) class assign_storage
Chris@16 445 //
Chris@16 446 // Internal visitor that assigns the given storage (which must be a
Chris@16 447 // constructed value of the same type) to the value it visits.
Chris@16 448 //
Chris@16 449 struct assign_storage
Chris@16 450 : public static_visitor<>
Chris@16 451 {
Chris@16 452 private: // representation
Chris@16 453
Chris@16 454 const void* rhs_storage_;
Chris@16 455
Chris@16 456 public: // structors
Chris@16 457
Chris@16 458 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
Chris@16 459 : rhs_storage_(rhs_storage)
Chris@16 460 {
Chris@16 461 }
Chris@16 462
Chris@16 463 public: // internal visitor interfaces
Chris@16 464
Chris@16 465 template <typename T>
Chris@16 466 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 467 internal_visit(backup_holder<T>& lhs_content, long) const
Chris@16 468 {
Chris@16 469 lhs_content.get()
Chris@16 470 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
Chris@16 471 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 472 }
Chris@16 473
Chris@16 474 template <typename T>
Chris@16 475 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 476 internal_visit(const backup_holder<T>& lhs_content, long) const
Chris@16 477 {
Chris@16 478 lhs_content.get()
Chris@16 479 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
Chris@16 480 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 481 }
Chris@16 482
Chris@16 483 template <typename T>
Chris@16 484 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 485 internal_visit(T& lhs_content, int) const
Chris@16 486 {
Chris@16 487 // NOTE TO USER :
Chris@16 488 // Compile error here indicates one of variant's bounded types does
Chris@16 489 // not meet the requirements of the Assignable concept. Thus,
Chris@16 490 // variant is not Assignable.
Chris@16 491 //
Chris@16 492 // Hint: Are any of the bounded types const-qualified or references?
Chris@16 493 //
Chris@16 494 lhs_content = *static_cast< const T* >(rhs_storage_);
Chris@16 495 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 496 }
Chris@16 497
Chris@16 498 };
Chris@16 499
Chris@16 500 ///////////////////////////////////////////////////////////////////////////////
Chris@16 501 // (detail) class move_storage
Chris@16 502 //
Chris@16 503 // Internal visitor that moves the given storage (which must be a
Chris@16 504 // constructed value of the same type) to the value it visits.
Chris@16 505 //
Chris@16 506 struct move_storage
Chris@16 507 : public static_visitor<>
Chris@16 508 {
Chris@16 509 private: // representation
Chris@16 510
Chris@16 511 void* rhs_storage_;
Chris@16 512
Chris@16 513 public: // structors
Chris@16 514
Chris@16 515 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
Chris@16 516 : rhs_storage_(rhs_storage)
Chris@16 517 {
Chris@16 518 }
Chris@16 519
Chris@16 520 public: // internal visitor interfaces
Chris@16 521
Chris@16 522 template <typename T>
Chris@16 523 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 524 internal_visit(backup_holder<T>& lhs_content, long) const
Chris@16 525 {
Chris@16 526 lhs_content.get()
Chris@16 527 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
Chris@16 528 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 529 }
Chris@16 530
Chris@16 531 template <typename T>
Chris@16 532 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 533 internal_visit(const backup_holder<T>& lhs_content, long) const
Chris@16 534 {
Chris@16 535 lhs_content.get()
Chris@16 536 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
Chris@16 537 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 538 }
Chris@16 539
Chris@16 540 template <typename T>
Chris@16 541 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 542 internal_visit(T& lhs_content, int) const
Chris@16 543 {
Chris@16 544 // NOTE TO USER :
Chris@16 545 // Compile error here indicates one of variant's bounded types does
Chris@16 546 // not meet the requirements of the Assignable concept. Thus,
Chris@16 547 // variant is not Assignable.
Chris@16 548 //
Chris@16 549 // Hint: Are any of the bounded types const-qualified or references?
Chris@16 550 //
Chris@16 551 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
Chris@16 552 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 553 }
Chris@16 554
Chris@16 555 };
Chris@16 556
Chris@16 557 ///////////////////////////////////////////////////////////////////////////////
Chris@16 558 // (detail) class direct_assigner
Chris@16 559 //
Chris@16 560 // Generic static visitor that: if and only if the visited value is of the
Chris@16 561 // specified type, assigns the given value to the visited value and returns
Chris@16 562 // true; else returns false.
Chris@16 563 //
Chris@16 564 template <typename T>
Chris@16 565 class direct_assigner
Chris@16 566 : public static_visitor<bool>
Chris@16 567 {
Chris@16 568 private: // representation
Chris@16 569
Chris@16 570 const T& rhs_;
Chris@16 571
Chris@16 572 public: // structors
Chris@16 573
Chris@16 574 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
Chris@16 575 : rhs_(rhs)
Chris@16 576 {
Chris@16 577 }
Chris@16 578
Chris@16 579 public: // visitor interface
Chris@16 580
Chris@16 581 bool operator()(T& lhs)
Chris@16 582 {
Chris@16 583 lhs = rhs_;
Chris@16 584 return true;
Chris@16 585 }
Chris@16 586
Chris@16 587 template <typename U>
Chris@16 588 bool operator()(U&) BOOST_NOEXCEPT
Chris@16 589 {
Chris@16 590 return false;
Chris@16 591 }
Chris@16 592
Chris@16 593 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 594 private:
Chris@16 595 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 596 direct_assigner& operator= (direct_assigner const&);
Chris@16 597 #endif
Chris@16 598 };
Chris@16 599
Chris@16 600 ///////////////////////////////////////////////////////////////////////////////
Chris@16 601 // (detail) class direct_mover
Chris@16 602 //
Chris@16 603 // Generic static visitor that: if and only if the visited value is of the
Chris@16 604 // specified type, move assigns the given value to the visited value and returns
Chris@16 605 // true; else returns false.
Chris@16 606 //
Chris@16 607 template <typename T>
Chris@16 608 class direct_mover
Chris@16 609 : public static_visitor<bool>
Chris@16 610 {
Chris@16 611 private: // representation
Chris@16 612
Chris@16 613 T& rhs_;
Chris@16 614
Chris@16 615 public: // structors
Chris@16 616
Chris@16 617 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
Chris@16 618 : rhs_(rhs)
Chris@16 619 {
Chris@16 620 }
Chris@16 621
Chris@16 622 public: // visitor interface
Chris@16 623
Chris@16 624 bool operator()(T& lhs)
Chris@16 625 {
Chris@16 626 lhs = ::boost::detail::variant::move(rhs_);
Chris@16 627 return true;
Chris@16 628 }
Chris@16 629
Chris@16 630 template <typename U>
Chris@16 631 bool operator()(U&) BOOST_NOEXCEPT
Chris@16 632 {
Chris@16 633 return false;
Chris@16 634 }
Chris@16 635
Chris@16 636 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 637 private:
Chris@16 638 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 639 direct_mover& operator= (direct_mover const&);
Chris@16 640 #endif
Chris@16 641 };
Chris@16 642
Chris@16 643
Chris@16 644 ///////////////////////////////////////////////////////////////////////////////
Chris@16 645 // (detail) class backup_assigner
Chris@16 646 //
Chris@16 647 // Internal visitor that "assigns" the given value to the visited value,
Chris@16 648 // using backup to recover if the destroy-copy sequence fails.
Chris@16 649 //
Chris@16 650 // NOTE: This needs to be a friend of variant, as it needs access to
Chris@16 651 // indicate_which, indicate_backup_which, etc.
Chris@16 652 //
Chris@16 653 template <typename Variant>
Chris@16 654 class backup_assigner
Chris@16 655 : public static_visitor<>
Chris@16 656 {
Chris@16 657 private: // representation
Chris@16 658
Chris@16 659 Variant& lhs_;
Chris@16 660 int rhs_which_;
Chris@16 661 const void* rhs_content_;
Chris@16 662 void (*copy_rhs_content_)(void*, const void*);
Chris@16 663
Chris@16 664 public: // structors
Chris@16 665
Chris@16 666 template<class RhsT>
Chris@16 667 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
Chris@16 668 : lhs_(lhs)
Chris@16 669 , rhs_which_(rhs_which)
Chris@16 670 , rhs_content_(&rhs_content)
Chris@16 671 , copy_rhs_content_(&construct_impl<RhsT>)
Chris@16 672 {
Chris@16 673 }
Chris@16 674
Chris@16 675 private: // helpers, for visitor interface (below)
Chris@16 676
Chris@16 677 template<class RhsT>
Chris@16 678 static void construct_impl(void* addr, const void* obj)
Chris@16 679 {
Chris@16 680 new(addr) RhsT(*static_cast<const RhsT*>(obj));
Chris@16 681 }
Chris@16 682
Chris@16 683 template <typename LhsT>
Chris@16 684 void backup_assign_impl(
Chris@101 685 backup_holder<LhsT>& lhs_content
Chris@101 686 , mpl::false_ // is_nothrow_move_constructible
Chris@101 687 , long
Chris@101 688 )
Chris@101 689 {
Chris@101 690 // Move lhs content to backup...
Chris@101 691 backup_holder<LhsT> backup_lhs_content(0);
Chris@101 692 backup_lhs_content.swap(lhs_content); // nothrow
Chris@101 693
Chris@101 694 // ...destroy lhs content...
Chris@101 695 lhs_content.~backup_holder<LhsT>(); // nothrow
Chris@101 696
Chris@101 697 BOOST_TRY
Chris@101 698 {
Chris@101 699 // ...and attempt to copy rhs content into lhs storage:
Chris@101 700 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
Chris@101 701 }
Chris@101 702 BOOST_CATCH (...)
Chris@101 703 {
Chris@101 704 // In case of failure, copy backup pointer to lhs storage...
Chris@101 705 new(lhs_.storage_.address())
Chris@101 706 backup_holder<LhsT>( 0 ); // nothrow
Chris@101 707
Chris@101 708 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
Chris@101 709 ->swap(backup_lhs_content); // nothrow
Chris@101 710
Chris@101 711 // ...and rethrow:
Chris@101 712 BOOST_RETHROW;
Chris@101 713 }
Chris@101 714 BOOST_CATCH_END
Chris@101 715
Chris@101 716 // In case of success, indicate new content type:
Chris@101 717 lhs_.indicate_which(rhs_which_); // nothrow
Chris@101 718 }
Chris@101 719
Chris@101 720 template <typename LhsT>
Chris@101 721 void backup_assign_impl(
Chris@16 722 LhsT& lhs_content
Chris@16 723 , mpl::true_ // is_nothrow_move_constructible
Chris@101 724 , int
Chris@16 725 )
Chris@16 726 {
Chris@16 727 // Move lhs content to backup...
Chris@16 728 LhsT backup_lhs_content(
Chris@16 729 ::boost::detail::variant::move(lhs_content)
Chris@16 730 ); // nothrow
Chris@16 731
Chris@16 732 // ...destroy lhs content...
Chris@16 733 lhs_content.~LhsT(); // nothrow
Chris@16 734
Chris@16 735 BOOST_TRY
Chris@16 736 {
Chris@16 737 // ...and attempt to copy rhs content into lhs storage:
Chris@16 738 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
Chris@16 739 }
Chris@16 740 BOOST_CATCH (...)
Chris@16 741 {
Chris@16 742 // In case of failure, restore backup content to lhs storage...
Chris@16 743 new(lhs_.storage_.address())
Chris@16 744 LhsT(
Chris@16 745 ::boost::detail::variant::move(backup_lhs_content)
Chris@16 746 ); // nothrow
Chris@16 747
Chris@16 748 // ...and rethrow:
Chris@16 749 BOOST_RETHROW;
Chris@16 750 }
Chris@16 751 BOOST_CATCH_END
Chris@16 752
Chris@16 753 // In case of success, indicate new content type:
Chris@16 754 lhs_.indicate_which(rhs_which_); // nothrow
Chris@16 755 }
Chris@16 756
Chris@16 757 template <typename LhsT>
Chris@16 758 void backup_assign_impl(
Chris@16 759 LhsT& lhs_content
Chris@16 760 , mpl::false_ // is_nothrow_move_constructible
Chris@101 761 , int
Chris@16 762 )
Chris@16 763 {
Chris@16 764 // Backup lhs content...
Chris@16 765 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
Chris@16 766
Chris@16 767 // ...destroy lhs content...
Chris@16 768 lhs_content.~LhsT(); // nothrow
Chris@16 769
Chris@16 770 BOOST_TRY
Chris@16 771 {
Chris@16 772 // ...and attempt to copy rhs content into lhs storage:
Chris@16 773 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
Chris@16 774 }
Chris@16 775 BOOST_CATCH (...)
Chris@16 776 {
Chris@16 777 // In case of failure, copy backup pointer to lhs storage...
Chris@16 778 new(lhs_.storage_.address())
Chris@16 779 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
Chris@16 780
Chris@16 781 // ...indicate now using backup...
Chris@16 782 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
Chris@16 783
Chris@16 784 // ...and rethrow:
Chris@16 785 BOOST_RETHROW;
Chris@16 786 }
Chris@16 787 BOOST_CATCH_END
Chris@16 788
Chris@16 789 // In case of success, indicate new content type...
Chris@16 790 lhs_.indicate_which(rhs_which_); // nothrow
Chris@16 791
Chris@16 792 // ...and delete backup:
Chris@16 793 delete backup_lhs_ptr; // nothrow
Chris@16 794 }
Chris@16 795
Chris@16 796 public: // visitor interface
Chris@16 797
Chris@16 798 template <typename LhsT>
Chris@16 799 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 800 internal_visit(LhsT& lhs_content, int)
Chris@16 801 {
Chris@16 802 typedef typename is_nothrow_move_constructible<LhsT>::type
Chris@16 803 nothrow_move;
Chris@16 804
Chris@101 805 backup_assign_impl( lhs_content, nothrow_move(), 1L);
Chris@16 806
Chris@16 807 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 808 }
Chris@16 809
Chris@16 810 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 811 private:
Chris@16 812 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 813 backup_assigner& operator= (backup_assigner const&);
Chris@16 814 #endif
Chris@16 815 };
Chris@16 816
Chris@16 817 ///////////////////////////////////////////////////////////////////////////////
Chris@16 818 // (detail) class swap_with
Chris@16 819 //
Chris@16 820 // Visitor that swaps visited value with content of given variant.
Chris@16 821 //
Chris@16 822 // Precondition: Given variant MUST have same logical type as visited value.
Chris@16 823 //
Chris@16 824 template <typename Variant>
Chris@16 825 struct swap_with
Chris@16 826 : public static_visitor<>
Chris@16 827 {
Chris@16 828 private: // representation
Chris@16 829
Chris@16 830 Variant& toswap_;
Chris@16 831
Chris@16 832 public: // structors
Chris@16 833
Chris@101 834 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
Chris@16 835 : toswap_(toswap)
Chris@16 836 {
Chris@16 837 }
Chris@16 838
Chris@16 839 public: // internal visitor interfaces
Chris@16 840
Chris@16 841 template <typename T>
Chris@16 842 void operator()(T& operand) const
Chris@16 843 {
Chris@16 844 // Since the precondition ensures types are same, get T...
Chris@16 845 known_get<T> getter;
Chris@16 846 T& other = toswap_.apply_visitor(getter);
Chris@16 847
Chris@16 848 // ...and swap:
Chris@16 849 ::boost::detail::variant::move_swap( operand, other );
Chris@16 850 }
Chris@16 851
Chris@16 852 private:
Chris@16 853 swap_with& operator=(const swap_with&);
Chris@16 854
Chris@16 855 };
Chris@16 856
Chris@16 857 ///////////////////////////////////////////////////////////////////////////////
Chris@16 858 // (detail) class reflect
Chris@16 859 //
Chris@16 860 // Generic static visitor that performs a typeid on the value it visits.
Chris@16 861 //
Chris@16 862
Chris@16 863 class reflect
Chris@101 864 : public static_visitor<const boost::typeindex::type_info&>
Chris@16 865 {
Chris@16 866 public: // visitor interfaces
Chris@16 867
Chris@16 868 template <typename T>
Chris@101 869 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
Chris@16 870 {
Chris@101 871 return boost::typeindex::type_id<T>().type_info();
Chris@16 872 }
Chris@16 873
Chris@16 874 };
Chris@16 875
Chris@16 876 ///////////////////////////////////////////////////////////////////////////////
Chris@16 877 // (detail) class comparer
Chris@16 878 //
Chris@16 879 // Generic static visitor that compares the content of the given lhs variant
Chris@16 880 // with the visited rhs content using Comp.
Chris@16 881 //
Chris@16 882 // Precondition: lhs.which() == rhs.which()
Chris@16 883 //
Chris@16 884 template <typename Variant, typename Comp>
Chris@16 885 class comparer
Chris@16 886 : public static_visitor<bool>
Chris@16 887 {
Chris@16 888 private: // representation
Chris@16 889
Chris@16 890 const Variant& lhs_;
Chris@16 891
Chris@16 892 public: // structors
Chris@16 893
Chris@16 894 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
Chris@16 895 : lhs_(lhs)
Chris@16 896 {
Chris@16 897 }
Chris@16 898
Chris@16 899 public: // visitor interfaces
Chris@16 900
Chris@16 901 template <typename T>
Chris@16 902 bool operator()(const T& rhs_content) const
Chris@16 903 {
Chris@16 904 // Since the precondition ensures lhs and rhs types are same, get T...
Chris@16 905 known_get<const T> getter;
Chris@16 906 const T& lhs_content = lhs_.apply_visitor(getter);
Chris@16 907
Chris@16 908 // ...and compare lhs and rhs contents:
Chris@16 909 return Comp()(lhs_content, rhs_content);
Chris@16 910 }
Chris@16 911
Chris@16 912 private:
Chris@16 913 comparer& operator=(const comparer&);
Chris@16 914
Chris@16 915 };
Chris@16 916
Chris@16 917 ///////////////////////////////////////////////////////////////////////////////
Chris@16 918 // (detail) class equal_comp
Chris@16 919 //
Chris@16 920 // Generic function object compares lhs with rhs using operator==.
Chris@16 921 //
Chris@16 922 struct equal_comp
Chris@16 923 {
Chris@16 924 template <typename T>
Chris@16 925 bool operator()(const T& lhs, const T& rhs) const
Chris@16 926 {
Chris@16 927 return lhs == rhs;
Chris@16 928 }
Chris@16 929 };
Chris@16 930
Chris@16 931 ///////////////////////////////////////////////////////////////////////////////
Chris@16 932 // (detail) class less_comp
Chris@16 933 //
Chris@16 934 // Generic function object compares lhs with rhs using operator<.
Chris@16 935 //
Chris@16 936 struct less_comp
Chris@16 937 {
Chris@16 938 template <typename T>
Chris@16 939 bool operator()(const T& lhs, const T& rhs) const
Chris@16 940 {
Chris@16 941 return lhs < rhs;
Chris@16 942 }
Chris@16 943 };
Chris@16 944
Chris@16 945 ///////////////////////////////////////////////////////////////////////////////
Chris@16 946 // (detail) class template invoke_visitor
Chris@16 947 //
Chris@16 948 // Internal visitor that invokes the given visitor using:
Chris@16 949 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
Chris@16 950 // * for all other values, the value itself.
Chris@16 951 //
Chris@16 952 template <typename Visitor>
Chris@16 953 class invoke_visitor
Chris@16 954 {
Chris@16 955 private: // representation
Chris@16 956
Chris@16 957 Visitor& visitor_;
Chris@16 958
Chris@16 959 public: // visitor typedefs
Chris@16 960
Chris@16 961 typedef typename Visitor::result_type
Chris@16 962 result_type;
Chris@16 963
Chris@16 964 public: // structors
Chris@16 965
Chris@16 966 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
Chris@16 967 : visitor_(visitor)
Chris@16 968 {
Chris@16 969 }
Chris@16 970
Chris@16 971 #if !defined(BOOST_NO_VOID_RETURNS)
Chris@16 972
Chris@16 973 public: // internal visitor interfaces
Chris@16 974
Chris@16 975 template <typename T>
Chris@16 976 result_type internal_visit(T& operand, int)
Chris@16 977 {
Chris@16 978 return visitor_(operand);
Chris@16 979 }
Chris@16 980
Chris@16 981 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
Chris@16 982 template <typename T>
Chris@16 983 result_type internal_visit(const T& operand, int)
Chris@16 984 {
Chris@16 985 return visitor_(operand);
Chris@16 986 }
Chris@16 987 # endif
Chris@16 988
Chris@16 989 #else // defined(BOOST_NO_VOID_RETURNS)
Chris@16 990
Chris@16 991 private: // helpers, for internal visitor interfaces (below)
Chris@16 992
Chris@16 993 template <typename T>
Chris@16 994 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 995 visit_impl(T& operand, mpl::false_)
Chris@16 996 {
Chris@16 997 return visitor_(operand);
Chris@16 998 }
Chris@16 999
Chris@16 1000 template <typename T>
Chris@16 1001 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@16 1002 visit_impl(T& operand, mpl::true_)
Chris@16 1003 {
Chris@16 1004 visitor_(operand);
Chris@16 1005 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 1006 }
Chris@16 1007
Chris@16 1008 public: // internal visitor interfaces
Chris@16 1009
Chris@16 1010 template <typename T>
Chris@16 1011 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1012 internal_visit(T& operand, int)
Chris@16 1013 {
Chris@16 1014 typedef typename is_same<result_type, void>::type
Chris@16 1015 has_void_result_type;
Chris@16 1016
Chris@16 1017 return visit_impl(operand, has_void_result_type());
Chris@16 1018 }
Chris@16 1019
Chris@16 1020 #endif // BOOST_NO_VOID_RETURNS) workaround
Chris@16 1021
Chris@16 1022 public: // internal visitor interfaces, cont.
Chris@16 1023
Chris@16 1024 template <typename T>
Chris@16 1025 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1026 internal_visit(boost::recursive_wrapper<T>& operand, long)
Chris@16 1027 {
Chris@16 1028 return internal_visit( operand.get(), 1L );
Chris@16 1029 }
Chris@16 1030
Chris@16 1031 template <typename T>
Chris@16 1032 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1033 internal_visit(const boost::recursive_wrapper<T>& operand, long)
Chris@16 1034 {
Chris@16 1035 return internal_visit( operand.get(), 1L );
Chris@16 1036 }
Chris@16 1037
Chris@16 1038 template <typename T>
Chris@16 1039 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1040 internal_visit(boost::detail::reference_content<T>& operand, long)
Chris@16 1041 {
Chris@16 1042 return internal_visit( operand.get(), 1L );
Chris@16 1043 }
Chris@16 1044
Chris@16 1045 template <typename T>
Chris@16 1046 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1047 internal_visit(const boost::detail::reference_content<T>& operand, long)
Chris@16 1048 {
Chris@16 1049 return internal_visit( operand.get(), 1L );
Chris@16 1050 }
Chris@16 1051
Chris@16 1052 template <typename T>
Chris@16 1053 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1054 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
Chris@16 1055 {
Chris@16 1056 return internal_visit( operand.get(), 1L );
Chris@16 1057 }
Chris@16 1058
Chris@16 1059 template <typename T>
Chris@16 1060 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
Chris@16 1061 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
Chris@16 1062 {
Chris@16 1063 return internal_visit( operand.get(), 1L );
Chris@16 1064 }
Chris@16 1065
Chris@16 1066 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 1067 private:
Chris@16 1068 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 1069 invoke_visitor& operator= (invoke_visitor const&);
Chris@16 1070 #endif
Chris@16 1071 };
Chris@16 1072
Chris@16 1073 }} // namespace detail::variant
Chris@16 1074
Chris@16 1075 ///////////////////////////////////////////////////////////////////////////////
Chris@16 1076 // class template variant (concept inspired by Andrei Alexandrescu)
Chris@16 1077 //
Chris@16 1078 // See docs and boost/variant/variant_fwd.hpp for more information.
Chris@16 1079 //
Chris@16 1080 template <
Chris@16 1081 typename T0_
Chris@16 1082 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
Chris@16 1083 >
Chris@16 1084 class variant
Chris@16 1085 {
Chris@16 1086 private: // helpers, for typedefs (below)
Chris@16 1087
Chris@16 1088 typedef variant wknd_self_t;
Chris@16 1089
Chris@16 1090 struct is_recursive_
Chris@16 1091 : detail::variant::is_recursive_flag<T0_>
Chris@16 1092 {
Chris@16 1093 };
Chris@16 1094
Chris@16 1095 typedef typename mpl::eval_if<
Chris@16 1096 is_recursive_
Chris@16 1097 , T0_
Chris@16 1098 , mpl::identity< T0_ >
Chris@16 1099 >::type unwrapped_T0_;
Chris@16 1100
Chris@16 1101 struct is_sequence_based_
Chris@16 1102 : detail::variant::is_over_sequence<unwrapped_T0_>
Chris@16 1103 {
Chris@16 1104 };
Chris@16 1105
Chris@16 1106 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
Chris@16 1107
Chris@16 1108 private: // helpers, for typedefs (below)
Chris@16 1109
Chris@16 1110 typedef typename mpl::eval_if<
Chris@16 1111 is_sequence_based_
Chris@16 1112 , unwrapped_T0_ // over_sequence<...>::type
Chris@16 1113 , detail::variant::make_variant_list<
Chris@16 1114 unwrapped_T0_
Chris@16 1115 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
Chris@16 1116 >
Chris@16 1117 >::type specified_types;
Chris@16 1118
Chris@16 1119 BOOST_STATIC_ASSERT((
Chris@16 1120 ::boost::mpl::not_< mpl::empty<specified_types> >::value
Chris@16 1121 ));
Chris@16 1122
Chris@16 1123 typedef typename mpl::eval_if<
Chris@16 1124 is_recursive_
Chris@16 1125 , mpl::transform<
Chris@16 1126 specified_types
Chris@16 1127 , mpl::protect<
Chris@16 1128 detail::variant::quoted_enable_recursive<wknd_self_t>
Chris@16 1129 >
Chris@16 1130 >
Chris@16 1131 , mpl::identity< specified_types >
Chris@16 1132 >::type recursive_enabled_types;
Chris@16 1133
Chris@16 1134 public: // public typedefs
Chris@16 1135
Chris@16 1136 typedef typename mpl::transform<
Chris@16 1137 recursive_enabled_types
Chris@16 1138 , unwrap_recursive<mpl::_1>
Chris@16 1139 >::type types;
Chris@16 1140
Chris@16 1141 private: // internal typedefs
Chris@16 1142
Chris@16 1143 typedef typename mpl::transform<
Chris@16 1144 recursive_enabled_types
Chris@16 1145 , mpl::protect< detail::make_reference_content<> >
Chris@16 1146 >::type internal_types;
Chris@16 1147
Chris@16 1148 typedef typename mpl::front<
Chris@16 1149 internal_types
Chris@16 1150 >::type internal_T0;
Chris@16 1151
Chris@16 1152 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
Chris@16 1153
Chris@16 1154 private: // helpers, for typedefs (below)
Chris@16 1155
Chris@16 1156 typedef unwrapped_T0_ T0;
Chris@16 1157
Chris@16 1158 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
Chris@16 1159 typedef typename mpl::eval_if< \
Chris@16 1160 is_recursive_ \
Chris@16 1161 , detail::variant::enable_recursive< \
Chris@16 1162 BOOST_PP_CAT(T,N) \
Chris@16 1163 , wknd_self_t \
Chris@16 1164 > \
Chris@16 1165 , mpl::identity< BOOST_PP_CAT(T,N) > \
Chris@16 1166 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
Chris@16 1167 /**/
Chris@16 1168
Chris@16 1169 BOOST_PP_REPEAT(
Chris@16 1170 BOOST_VARIANT_LIMIT_TYPES
Chris@16 1171 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
Chris@16 1172 , _
Chris@16 1173 )
Chris@16 1174
Chris@16 1175 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
Chris@16 1176
Chris@16 1177 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
Chris@16 1178 typedef typename unwrap_recursive< \
Chris@16 1179 BOOST_PP_CAT(recursive_enabled_T,N) \
Chris@16 1180 >::type BOOST_PP_CAT(public_T,N); \
Chris@16 1181 /**/
Chris@16 1182
Chris@16 1183 BOOST_PP_REPEAT(
Chris@16 1184 BOOST_VARIANT_LIMIT_TYPES
Chris@16 1185 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
Chris@16 1186 , _
Chris@16 1187 )
Chris@16 1188
Chris@16 1189 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
Chris@16 1190
Chris@16 1191 public: // public typedefs
Chris@16 1192
Chris@16 1193 typedef typename detail::variant::make_variant_list<
Chris@16 1194 BOOST_VARIANT_ENUM_PARAMS(public_T)
Chris@16 1195 >::type types;
Chris@16 1196
Chris@16 1197 private: // helpers, for internal typedefs (below)
Chris@16 1198
Chris@16 1199 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
Chris@16 1200 typedef detail::make_reference_content< \
Chris@16 1201 BOOST_PP_CAT(recursive_enabled_T,N) \
Chris@16 1202 >::type BOOST_PP_CAT(internal_T,N); \
Chris@16 1203 /**/
Chris@16 1204
Chris@16 1205 BOOST_PP_REPEAT(
Chris@16 1206 BOOST_VARIANT_LIMIT_TYPES
Chris@16 1207 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
Chris@16 1208 , _
Chris@16 1209 )
Chris@16 1210
Chris@16 1211 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
Chris@16 1212
Chris@16 1213 private: // internal typedefs
Chris@16 1214
Chris@16 1215 typedef typename detail::variant::make_variant_list<
Chris@16 1216 BOOST_VARIANT_ENUM_PARAMS(internal_T)
Chris@16 1217 >::type internal_types;
Chris@16 1218
Chris@16 1219 private: // static precondition assertions
Chris@16 1220
Chris@16 1221 // NOTE TO USER :
Chris@16 1222 // variant< type-sequence > syntax is not supported on this compiler!
Chris@16 1223 //
Chris@16 1224 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
Chris@16 1225
Chris@16 1226 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
Chris@16 1227
Chris@16 1228 private: // helpers, for representation (below)
Chris@16 1229
Chris@16 1230 typedef typename detail::variant::find_fallback_type<
Chris@16 1231 internal_types
Chris@16 1232 >::type fallback_type_result_;
Chris@16 1233
Chris@16 1234 typedef typename fallback_type_result_::first
Chris@16 1235 fallback_type_index_;
Chris@16 1236 typedef typename fallback_type_result_::second
Chris@16 1237 fallback_type_;
Chris@16 1238
Chris@16 1239 struct has_fallback_type_
Chris@16 1240 : mpl::not_<
Chris@16 1241 is_same< fallback_type_, detail::variant::no_fallback_type >
Chris@16 1242 >
Chris@16 1243 {
Chris@16 1244 };
Chris@16 1245
Chris@16 1246 typedef has_fallback_type_
Chris@16 1247 never_uses_backup_flag;
Chris@16 1248
Chris@16 1249 typedef typename detail::variant::make_storage<
Chris@16 1250 internal_types, never_uses_backup_flag
Chris@16 1251 >::type storage_t;
Chris@16 1252
Chris@16 1253 #ifndef BOOST_NO_CXX11_NOEXCEPT
Chris@101 1254 typedef typename detail::variant::is_variant_move_noexcept_constructible<
Chris@16 1255 internal_types
Chris@101 1256 > variant_move_noexcept_constructible;
Chris@101 1257
Chris@101 1258 typedef typename detail::variant::is_variant_move_noexcept_assignable<
Chris@101 1259 internal_types
Chris@101 1260 > variant_move_noexcept_assignable;
Chris@101 1261
Chris@16 1262 #endif
Chris@16 1263
Chris@16 1264 private: // helpers, for representation (below)
Chris@16 1265
Chris@16 1266 // which_ on:
Chris@16 1267 // * [0, size<internal_types>) indicates stack content
Chris@16 1268 // * [-size<internal_types>, 0) indicates pointer to heap backup
Chris@16 1269 // if which_ >= 0:
Chris@16 1270 // * then which() -> which_
Chris@16 1271 // * else which() -> -(which_ + 1)
Chris@16 1272
Chris@16 1273 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
Chris@16 1274
Chris@16 1275 typedef int which_t;
Chris@16 1276
Chris@16 1277 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
Chris@16 1278
Chris@16 1279 // [if O1_size available, then attempt which_t size optimization...]
Chris@16 1280 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
Chris@16 1281 typedef typename mpl::eval_if<
Chris@16 1282 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
Chris@16 1283 , mpl::identity< int >
Chris@16 1284 , mpl::if_<
Chris@16 1285 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
Chris@16 1286 , signed char
Chris@16 1287 , int
Chris@16 1288 >
Chris@16 1289 >::type which_t;
Chris@16 1290
Chris@16 1291 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
Chris@16 1292
Chris@16 1293 // representation -- private when possible
Chris@16 1294 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
Chris@16 1295 private:
Chris@16 1296 #else
Chris@16 1297 public:
Chris@16 1298 #endif
Chris@16 1299
Chris@16 1300 which_t which_;
Chris@16 1301 storage_t storage_;
Chris@16 1302
Chris@16 1303 void indicate_which(int which_arg) BOOST_NOEXCEPT
Chris@16 1304 {
Chris@16 1305 which_ = static_cast<which_t>( which_arg );
Chris@16 1306 }
Chris@16 1307
Chris@16 1308 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
Chris@16 1309 {
Chris@16 1310 which_ = static_cast<which_t>( -(which_arg + 1) );
Chris@16 1311 }
Chris@16 1312
Chris@16 1313 private: // helpers, for queries (below)
Chris@16 1314
Chris@16 1315 bool using_backup() const BOOST_NOEXCEPT
Chris@16 1316 {
Chris@16 1317 return which_ < 0;
Chris@16 1318 }
Chris@16 1319
Chris@16 1320 public: // queries
Chris@16 1321
Chris@16 1322 int which() const BOOST_NOEXCEPT
Chris@16 1323 {
Chris@16 1324 // If using heap backup...
Chris@16 1325 if (using_backup())
Chris@16 1326 // ...then return adjusted which_:
Chris@16 1327 return -(which_ + 1);
Chris@16 1328
Chris@16 1329 // Otherwise, return which_ directly:
Chris@16 1330 return which_;
Chris@16 1331 }
Chris@16 1332
Chris@16 1333 private: // helpers, for structors (below)
Chris@16 1334
Chris@16 1335 struct initializer
Chris@16 1336 : BOOST_VARIANT_AUX_INITIALIZER_T(
Chris@16 1337 recursive_enabled_types, recursive_enabled_T
Chris@16 1338 )
Chris@16 1339 {
Chris@16 1340 };
Chris@16 1341
Chris@101 1342 void destroy_content() BOOST_NOEXCEPT
Chris@16 1343 {
Chris@16 1344 detail::variant::destroyer visitor;
Chris@16 1345 this->internal_apply_visitor(visitor);
Chris@16 1346 }
Chris@16 1347
Chris@16 1348 public: // structors
Chris@16 1349
Chris@16 1350 ~variant() BOOST_NOEXCEPT
Chris@16 1351 {
Chris@16 1352 destroy_content();
Chris@16 1353 }
Chris@16 1354
Chris@101 1355 variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
Chris@16 1356 {
Chris@101 1357 #ifdef _MSC_VER
Chris@101 1358 #pragma warning( push )
Chris@101 1359 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
Chris@101 1360 #pragma warning( disable : 4345 )
Chris@101 1361 #endif
Chris@16 1362 // NOTE TO USER :
Chris@16 1363 // Compile error from here indicates that the first bound
Chris@16 1364 // type is not default-constructible, and so variant cannot
Chris@16 1365 // support its own default-construction.
Chris@16 1366 //
Chris@16 1367 new( storage_.address() ) internal_T0();
Chris@16 1368 indicate_which(0); // zero is the index of the first bounded type
Chris@101 1369 #ifdef _MSC_VER
Chris@101 1370 #pragma warning( pop )
Chris@101 1371 #endif
Chris@16 1372 }
Chris@16 1373
Chris@16 1374 private: // helpers, for structors, cont. (below)
Chris@16 1375
Chris@16 1376 class convert_copy_into
Chris@16 1377 : public static_visitor<int>
Chris@16 1378 {
Chris@16 1379 private: // representation
Chris@16 1380
Chris@16 1381 void* storage_;
Chris@16 1382
Chris@16 1383 public: // structors
Chris@16 1384
Chris@16 1385 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
Chris@16 1386 : storage_(storage)
Chris@16 1387 {
Chris@16 1388 }
Chris@16 1389
Chris@16 1390 public: // internal visitor interfaces (below)
Chris@16 1391
Chris@16 1392 template <typename T>
Chris@16 1393 int internal_visit(T& operand, int) const
Chris@16 1394 {
Chris@16 1395 // NOTE TO USER :
Chris@16 1396 // Compile error here indicates one of the source variant's types
Chris@16 1397 // cannot be unambiguously converted to the destination variant's
Chris@16 1398 // types (or that no conversion exists).
Chris@16 1399 //
Chris@16 1400 return initializer::initialize(storage_, operand);
Chris@16 1401 }
Chris@16 1402
Chris@16 1403 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
Chris@16 1404 template <typename T>
Chris@16 1405 result_type internal_visit(const T& operand, int) const
Chris@16 1406 {
Chris@16 1407 return initializer::initialize(storage_, operand);
Chris@16 1408 }
Chris@16 1409 # endif
Chris@16 1410
Chris@16 1411 template <typename T>
Chris@16 1412 int internal_visit(boost::detail::reference_content<T>& operand, long) const
Chris@16 1413 {
Chris@16 1414 return internal_visit( operand.get(), 1L );
Chris@16 1415 }
Chris@16 1416
Chris@16 1417 template <typename T>
Chris@16 1418 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
Chris@16 1419 {
Chris@16 1420 return internal_visit( operand.get(), 1L );
Chris@16 1421 }
Chris@16 1422
Chris@16 1423 template <typename T>
Chris@16 1424 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 1425 {
Chris@16 1426 return internal_visit( operand.get(), 1L );
Chris@16 1427 }
Chris@16 1428
Chris@16 1429 template <typename T>
Chris@16 1430 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 1431 {
Chris@16 1432 return internal_visit( operand.get(), 1L );
Chris@16 1433 }
Chris@16 1434
Chris@16 1435 template <typename T>
Chris@16 1436 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
Chris@16 1437 {
Chris@16 1438 return internal_visit( operand.get(), 1L );
Chris@16 1439 }
Chris@16 1440
Chris@16 1441 template <typename T>
Chris@16 1442 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
Chris@16 1443 {
Chris@16 1444 return internal_visit( operand.get(), 1L );
Chris@16 1445 }
Chris@16 1446
Chris@16 1447 };
Chris@16 1448
Chris@16 1449 friend class convert_copy_into;
Chris@16 1450
Chris@16 1451 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1452 class convert_move_into
Chris@16 1453 : public static_visitor<int>
Chris@16 1454 {
Chris@16 1455 private: // representation
Chris@16 1456
Chris@16 1457 void* storage_;
Chris@16 1458
Chris@16 1459 public: // structors
Chris@16 1460
Chris@16 1461 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
Chris@16 1462 : storage_(storage)
Chris@16 1463 {
Chris@16 1464 }
Chris@16 1465
Chris@16 1466 public: // internal visitor interfaces (below)
Chris@16 1467
Chris@16 1468 template <typename T>
Chris@16 1469 int internal_visit(T& operand, int) const
Chris@16 1470 {
Chris@16 1471 // NOTE TO USER :
Chris@16 1472 // Compile error here indicates one of the source variant's types
Chris@16 1473 // cannot be unambiguously converted to the destination variant's
Chris@16 1474 // types (or that no conversion exists).
Chris@16 1475 //
Chris@16 1476 return initializer::initialize(storage_, detail::variant::move(operand) );
Chris@16 1477 }
Chris@16 1478
Chris@16 1479 template <typename T>
Chris@16 1480 int internal_visit(boost::detail::reference_content<T>& operand, long) const
Chris@16 1481 {
Chris@16 1482 return internal_visit( operand.get(), 1L );
Chris@16 1483 }
Chris@16 1484
Chris@16 1485 template <typename T>
Chris@16 1486 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
Chris@16 1487 {
Chris@16 1488 return internal_visit( operand.get(), 1L );
Chris@16 1489 }
Chris@16 1490
Chris@16 1491 template <typename T>
Chris@16 1492 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 1493 {
Chris@16 1494 return internal_visit( operand.get(), 1L );
Chris@16 1495 }
Chris@16 1496
Chris@16 1497 template <typename T>
Chris@16 1498 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
Chris@16 1499 {
Chris@16 1500 return internal_visit( operand.get(), 1L );
Chris@16 1501 }
Chris@16 1502
Chris@16 1503 template <typename T>
Chris@16 1504 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
Chris@16 1505 {
Chris@16 1506 return internal_visit( operand.get(), 1L );
Chris@16 1507 }
Chris@16 1508
Chris@16 1509 template <typename T>
Chris@16 1510 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
Chris@16 1511 {
Chris@16 1512 return internal_visit( operand.get(), 1L );
Chris@16 1513 }
Chris@16 1514 };
Chris@16 1515
Chris@16 1516 friend class convert_move_into;
Chris@16 1517 #endif
Chris@16 1518
Chris@16 1519 private: // helpers, for structors, below
Chris@16 1520
Chris@16 1521 template <typename T>
Chris@16 1522 void convert_construct(
Chris@16 1523 T& operand
Chris@16 1524 , int
Chris@16 1525 , mpl::false_ = mpl::false_() // is_foreign_variant
Chris@16 1526 )
Chris@16 1527 {
Chris@16 1528 // NOTE TO USER :
Chris@16 1529 // Compile error here indicates that the given type is not
Chris@16 1530 // unambiguously convertible to one of the variant's types
Chris@16 1531 // (or that no conversion exists).
Chris@16 1532 //
Chris@16 1533 indicate_which(
Chris@16 1534 initializer::initialize(
Chris@16 1535 storage_.address()
Chris@16 1536 , operand
Chris@16 1537 )
Chris@16 1538 );
Chris@16 1539 }
Chris@16 1540
Chris@16 1541 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1542 template <typename T>
Chris@16 1543 typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
Chris@16 1544 T&& operand
Chris@16 1545 , int
Chris@16 1546 , mpl::false_ = mpl::false_() // is_foreign_variant
Chris@16 1547 )
Chris@16 1548 {
Chris@16 1549 // NOTE TO USER :
Chris@16 1550 // Compile error here indicates that the given type is not
Chris@16 1551 // unambiguously convertible to one of the variant's types
Chris@16 1552 // (or that no conversion exists).
Chris@16 1553 //
Chris@16 1554 indicate_which(
Chris@16 1555 initializer::initialize(
Chris@16 1556 storage_.address()
Chris@16 1557 , detail::variant::move(operand)
Chris@16 1558 )
Chris@16 1559 );
Chris@16 1560 }
Chris@16 1561 #endif
Chris@16 1562
Chris@16 1563 template <typename Variant>
Chris@16 1564 void convert_construct(
Chris@16 1565 Variant& operand
Chris@16 1566 , long
Chris@16 1567 , mpl::true_// is_foreign_variant
Chris@16 1568 )
Chris@16 1569 {
Chris@16 1570 convert_copy_into visitor(storage_.address());
Chris@16 1571 indicate_which(
Chris@16 1572 operand.internal_apply_visitor(visitor)
Chris@16 1573 );
Chris@16 1574 }
Chris@16 1575
Chris@16 1576 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1577 template <typename Variant>
Chris@16 1578 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
Chris@16 1579 Variant&& operand
Chris@16 1580 , long
Chris@16 1581 , mpl::true_// is_foreign_variant
Chris@16 1582 )
Chris@16 1583 {
Chris@16 1584 convert_move_into visitor(storage_.address());
Chris@16 1585 indicate_which(
Chris@16 1586 operand.internal_apply_visitor(visitor)
Chris@16 1587 );
Chris@16 1588 }
Chris@16 1589 #endif
Chris@16 1590
Chris@16 1591 template <typename Variant>
Chris@16 1592 void convert_construct_variant(Variant& operand)
Chris@16 1593 {
Chris@16 1594 // [Determine if the given variant is itself a bounded type, or if its
Chris@16 1595 // content needs to be converted (i.e., it is a 'foreign' variant):]
Chris@16 1596 //
Chris@16 1597
Chris@16 1598 typedef typename mpl::find_if<
Chris@16 1599 types
Chris@16 1600 , is_same<
Chris@16 1601 add_const<mpl::_1>
Chris@16 1602 , const Variant
Chris@16 1603 >
Chris@16 1604 >::type found_it;
Chris@16 1605
Chris@16 1606 typedef typename mpl::end<types>::type not_found;
Chris@16 1607 typedef typename is_same<
Chris@16 1608 found_it, not_found
Chris@16 1609 >::type is_foreign_variant;
Chris@16 1610
Chris@16 1611 // Convert construct from operand:
Chris@16 1612 convert_construct(
Chris@16 1613 operand, 1L
Chris@16 1614 , is_foreign_variant()
Chris@16 1615 );
Chris@16 1616 }
Chris@16 1617
Chris@16 1618 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1619 template <typename Variant>
Chris@16 1620 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
Chris@16 1621 {
Chris@16 1622 // [Determine if the given variant is itself a bounded type, or if its
Chris@16 1623 // content needs to be converted (i.e., it is a 'foreign' variant):]
Chris@16 1624 //
Chris@16 1625
Chris@16 1626 typedef typename mpl::find_if<
Chris@16 1627 types
Chris@16 1628 , is_same<
Chris@16 1629 add_const<mpl::_1>
Chris@16 1630 , const Variant
Chris@16 1631 >
Chris@16 1632 >::type found_it;
Chris@16 1633
Chris@16 1634 typedef typename mpl::end<types>::type not_found;
Chris@16 1635 typedef typename is_same<
Chris@16 1636 found_it, not_found
Chris@16 1637 >::type is_foreign_variant;
Chris@16 1638
Chris@16 1639 // Convert move construct from operand:
Chris@16 1640 convert_construct(
Chris@16 1641 detail::variant::move(operand), 1L
Chris@16 1642 , is_foreign_variant()
Chris@16 1643 );
Chris@16 1644 }
Chris@16 1645 #endif
Chris@16 1646
Chris@16 1647 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
Chris@16 1648 void convert_construct(
Chris@16 1649 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
Chris@16 1650 , long
Chris@16 1651 )
Chris@16 1652 {
Chris@16 1653 convert_construct_variant(operand);
Chris@16 1654 }
Chris@16 1655
Chris@16 1656 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
Chris@16 1657 void convert_construct(
Chris@16 1658 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
Chris@16 1659 , long
Chris@16 1660 )
Chris@16 1661 {
Chris@16 1662 convert_construct_variant(operand);
Chris@16 1663 }
Chris@16 1664
Chris@16 1665 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1666 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
Chris@16 1667 void convert_construct(
Chris@16 1668 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
Chris@16 1669 , long
Chris@16 1670 )
Chris@16 1671 {
Chris@16 1672 convert_construct_variant( detail::variant::move(operand) );
Chris@16 1673 }
Chris@16 1674 #endif
Chris@16 1675
Chris@16 1676 public: // structors, cont.
Chris@16 1677
Chris@16 1678 #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
Chris@16 1679
Chris@16 1680 template <typename T>
Chris@16 1681 variant(const T& operand)
Chris@16 1682 {
Chris@16 1683 convert_construct(operand, 1L);
Chris@16 1684 }
Chris@16 1685
Chris@16 1686 template <typename T>
Chris@16 1687 variant(T& operand)
Chris@16 1688 {
Chris@16 1689 convert_construct(operand, 1L);
Chris@16 1690 }
Chris@16 1691
Chris@16 1692 #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
Chris@16 1693
Chris@16 1694 // For compilers that cannot distinguish between T& and const T& in
Chris@16 1695 // template constructors, but do fully support SFINAE, we can workaround:
Chris@16 1696
Chris@16 1697 template <typename T>
Chris@16 1698 variant(const T& operand)
Chris@16 1699 {
Chris@16 1700 convert_construct(operand, 1L);
Chris@16 1701 }
Chris@16 1702
Chris@16 1703 template <typename T>
Chris@16 1704 variant(
Chris@16 1705 T& operand
Chris@16 1706 , typename enable_if<
Chris@16 1707 mpl::not_< is_const<T> >
Chris@16 1708 , void
Chris@16 1709 >::type* = 0
Chris@16 1710 )
Chris@16 1711 {
Chris@16 1712 convert_construct(operand, 1L);
Chris@16 1713 }
Chris@16 1714
Chris@16 1715 #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
Chris@16 1716
Chris@16 1717 // For compilers that cannot distinguish between T& and const T& in
Chris@16 1718 // template constructors, and do NOT support SFINAE, we can't workaround:
Chris@16 1719
Chris@16 1720 template <typename T>
Chris@16 1721 variant(const T& operand)
Chris@16 1722 {
Chris@16 1723 convert_construct(operand, 1L);
Chris@16 1724 }
Chris@16 1725 #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
Chris@16 1726
Chris@16 1727 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1728 template <class T>
Chris@16 1729 variant(T&& operand, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0,
Chris@16 1730 typename boost::disable_if<boost::is_const<T> >::type* = 0)
Chris@16 1731 {
Chris@16 1732 convert_construct( detail::variant::move(operand), 1L);
Chris@16 1733 }
Chris@16 1734 #endif
Chris@16 1735
Chris@16 1736 public: // structors, cont.
Chris@16 1737
Chris@16 1738 // [MSVC6 requires copy constructor appear after template constructors]
Chris@16 1739 variant(const variant& operand)
Chris@16 1740 {
Chris@16 1741 // Copy the value of operand into *this...
Chris@16 1742 detail::variant::copy_into visitor( storage_.address() );
Chris@16 1743 operand.internal_apply_visitor(visitor);
Chris@16 1744
Chris@16 1745 // ...and activate the *this's primary storage on success:
Chris@16 1746 indicate_which(operand.which());
Chris@16 1747 }
Chris@16 1748
Chris@16 1749 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@101 1750 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
Chris@16 1751 {
Chris@16 1752 // Move the value of operand into *this...
Chris@16 1753 detail::variant::move_into visitor( storage_.address() );
Chris@16 1754 operand.internal_apply_visitor(visitor);
Chris@16 1755
Chris@16 1756 // ...and activate the *this's primary storage on success:
Chris@16 1757 indicate_which(operand.which());
Chris@16 1758 }
Chris@16 1759 #endif
Chris@16 1760
Chris@16 1761 private: // helpers, for modifiers (below)
Chris@16 1762
Chris@16 1763 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
Chris@16 1764 template <typename Variant>
Chris@16 1765 friend class detail::variant::backup_assigner;
Chris@16 1766 # endif
Chris@16 1767
Chris@16 1768 // class assigner
Chris@16 1769 //
Chris@16 1770 // Internal visitor that "assigns" the visited value to the given variant
Chris@16 1771 // by appropriate destruction and copy-construction.
Chris@16 1772 //
Chris@16 1773
Chris@16 1774 class assigner
Chris@16 1775 : public static_visitor<>
Chris@16 1776 {
Chris@101 1777 protected: // representation
Chris@16 1778
Chris@16 1779 variant& lhs_;
Chris@101 1780 const int rhs_which_;
Chris@16 1781
Chris@16 1782 public: // structors
Chris@16 1783
Chris@16 1784 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
Chris@16 1785 : lhs_(lhs)
Chris@16 1786 , rhs_which_(rhs_which)
Chris@16 1787 {
Chris@16 1788 }
Chris@16 1789
Chris@101 1790 protected: // helpers, for internal visitor interface (below)
Chris@16 1791
Chris@16 1792 template <typename RhsT, typename B1, typename B2>
Chris@16 1793 void assign_impl(
Chris@16 1794 const RhsT& rhs_content
Chris@16 1795 , mpl::true_ // has_nothrow_copy
Chris@16 1796 , B1 // is_nothrow_move_constructible
Chris@16 1797 , B2 // has_fallback_type
Chris@101 1798 ) const BOOST_NOEXCEPT
Chris@16 1799 {
Chris@16 1800 // Destroy lhs's content...
Chris@16 1801 lhs_.destroy_content(); // nothrow
Chris@16 1802
Chris@16 1803 // ...copy rhs content into lhs's storage...
Chris@16 1804 new(lhs_.storage_.address())
Chris@16 1805 RhsT( rhs_content ); // nothrow
Chris@16 1806
Chris@16 1807 // ...and indicate new content type:
Chris@16 1808 lhs_.indicate_which(rhs_which_); // nothrow
Chris@16 1809 }
Chris@16 1810
Chris@16 1811 template <typename RhsT, typename B>
Chris@16 1812 void assign_impl(
Chris@16 1813 const RhsT& rhs_content
Chris@16 1814 , mpl::false_ // has_nothrow_copy
Chris@16 1815 , mpl::true_ // is_nothrow_move_constructible
Chris@16 1816 , B // has_fallback_type
Chris@101 1817 ) const
Chris@16 1818 {
Chris@16 1819 // Attempt to make a temporary copy (so as to move it below)...
Chris@16 1820 RhsT temp(rhs_content);
Chris@16 1821
Chris@16 1822 // ...and upon success destroy lhs's content...
Chris@16 1823 lhs_.destroy_content(); // nothrow
Chris@16 1824
Chris@16 1825 // ...move the temporary copy into lhs's storage...
Chris@16 1826 new(lhs_.storage_.address())
Chris@16 1827 RhsT( detail::variant::move(temp) ); // nothrow
Chris@16 1828
Chris@16 1829 // ...and indicate new content type:
Chris@16 1830 lhs_.indicate_which(rhs_which_); // nothrow
Chris@16 1831 }
Chris@16 1832
Chris@101 1833 void construct_fallback() const BOOST_NOEXCEPT {
Chris@101 1834 // In case of failure, default-construct fallback type in lhs's storage...
Chris@101 1835 new (lhs_.storage_.address())
Chris@101 1836 fallback_type_; // nothrow
Chris@101 1837
Chris@101 1838 // ...indicate construction of fallback type...
Chris@101 1839 lhs_.indicate_which(
Chris@101 1840 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
Chris@101 1841 ); // nothrow
Chris@101 1842 }
Chris@101 1843
Chris@16 1844 template <typename RhsT>
Chris@16 1845 void assign_impl(
Chris@16 1846 const RhsT& rhs_content
Chris@16 1847 , mpl::false_ // has_nothrow_copy
Chris@16 1848 , mpl::false_ // is_nothrow_move_constructible
Chris@16 1849 , mpl::true_ // has_fallback_type
Chris@101 1850 ) const
Chris@16 1851 {
Chris@16 1852 // Destroy lhs's content...
Chris@16 1853 lhs_.destroy_content(); // nothrow
Chris@16 1854
Chris@16 1855 BOOST_TRY
Chris@16 1856 {
Chris@16 1857 // ...and attempt to copy rhs's content into lhs's storage:
Chris@16 1858 new(lhs_.storage_.address())
Chris@16 1859 RhsT( rhs_content );
Chris@16 1860 }
Chris@16 1861 BOOST_CATCH (...)
Chris@16 1862 {
Chris@101 1863 construct_fallback();
Chris@16 1864
Chris@16 1865 // ...and rethrow:
Chris@16 1866 BOOST_RETHROW;
Chris@16 1867 }
Chris@16 1868 BOOST_CATCH_END
Chris@16 1869
Chris@16 1870 // In the event of success, indicate new content type:
Chris@16 1871 lhs_.indicate_which(rhs_which_); // nothrow
Chris@16 1872 }
Chris@16 1873
Chris@16 1874 template <typename RhsT>
Chris@16 1875 void assign_impl(
Chris@16 1876 const RhsT& rhs_content
Chris@16 1877 , mpl::false_ // has_nothrow_copy
Chris@16 1878 , mpl::false_ // is_nothrow_move_constructible
Chris@16 1879 , mpl::false_ // has_fallback_type
Chris@101 1880 ) const
Chris@16 1881 {
Chris@16 1882 detail::variant::backup_assigner<wknd_self_t>
Chris@16 1883 visitor(lhs_, rhs_which_, rhs_content);
Chris@16 1884 lhs_.internal_apply_visitor(visitor);
Chris@16 1885 }
Chris@16 1886
Chris@16 1887 public: // internal visitor interfaces
Chris@16 1888
Chris@16 1889 template <typename RhsT>
Chris@16 1890 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@101 1891 internal_visit(const RhsT& rhs_content, int) const
Chris@16 1892 {
Chris@16 1893 typedef typename has_nothrow_copy<RhsT>::type
Chris@16 1894 nothrow_copy;
Chris@16 1895 typedef typename mpl::or_< // reduces compile-time
Chris@16 1896 nothrow_copy
Chris@16 1897 , is_nothrow_move_constructible<RhsT>
Chris@16 1898 >::type nothrow_move_constructor;
Chris@16 1899
Chris@16 1900 assign_impl(
Chris@16 1901 rhs_content
Chris@16 1902 , nothrow_copy()
Chris@16 1903 , nothrow_move_constructor()
Chris@16 1904 , has_fallback_type_()
Chris@16 1905 );
Chris@16 1906
Chris@16 1907 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 1908 }
Chris@16 1909
Chris@16 1910 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 1911 private:
Chris@16 1912 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 1913 assigner& operator= (assigner const&);
Chris@16 1914 #endif
Chris@16 1915 };
Chris@16 1916
Chris@16 1917 friend class assigner;
Chris@16 1918
Chris@16 1919 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 1920 // class move_assigner
Chris@16 1921 //
Chris@16 1922 // Internal visitor that "move assigns" the visited value to the given variant
Chris@16 1923 // by appropriate destruction and move-construction.
Chris@16 1924 //
Chris@16 1925
Chris@16 1926 class move_assigner
Chris@101 1927 : public assigner
Chris@16 1928 {
Chris@16 1929 public: // structors
Chris@16 1930
Chris@16 1931 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
Chris@101 1932 : assigner(lhs, rhs_which)
Chris@16 1933 {
Chris@16 1934 }
Chris@16 1935
Chris@16 1936 private: // helpers, for internal visitor interface (below)
Chris@101 1937
Chris@16 1938 template <typename RhsT, typename B2>
Chris@16 1939 void assign_impl(
Chris@16 1940 RhsT& rhs_content
Chris@16 1941 , mpl::true_ // has_nothrow_copy
Chris@16 1942 , mpl::false_ // is_nothrow_move_constructible
Chris@16 1943 , B2 // has_fallback_type
Chris@101 1944 ) const BOOST_NOEXCEPT
Chris@16 1945 {
Chris@101 1946 assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
Chris@16 1947 }
Chris@16 1948
Chris@101 1949 template <typename RhsT, typename B, typename B2>
Chris@16 1950 void assign_impl(
Chris@16 1951 RhsT& rhs_content
Chris@101 1952 , B // has_nothrow_copy
Chris@16 1953 , mpl::true_ // is_nothrow_move_constructible
Chris@101 1954 , B2 // has_fallback_type
Chris@101 1955 ) const BOOST_NOEXCEPT
Chris@16 1956 {
Chris@16 1957 // ...destroy lhs's content...
Chris@101 1958 assigner::lhs_.destroy_content(); // nothrow
Chris@16 1959
Chris@16 1960 // ...move the rhs_content into lhs's storage...
Chris@101 1961 new(assigner::lhs_.storage_.address())
Chris@16 1962 RhsT( detail::variant::move(rhs_content) ); // nothrow
Chris@16 1963
Chris@16 1964 // ...and indicate new content type:
Chris@101 1965 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
Chris@16 1966 }
Chris@16 1967
Chris@16 1968 template <typename RhsT>
Chris@16 1969 void assign_impl(
Chris@16 1970 RhsT& rhs_content
Chris@16 1971 , mpl::false_ // has_nothrow_copy
Chris@16 1972 , mpl::false_ // is_nothrow_move_constructible
Chris@16 1973 , mpl::true_ // has_fallback_type
Chris@101 1974 ) const
Chris@16 1975 {
Chris@16 1976 // Destroy lhs's content...
Chris@101 1977 assigner::lhs_.destroy_content(); // nothrow
Chris@16 1978
Chris@16 1979 BOOST_TRY
Chris@16 1980 {
Chris@16 1981 // ...and attempt to copy rhs's content into lhs's storage:
Chris@101 1982 new(assigner::lhs_.storage_.address())
Chris@16 1983 RhsT( detail::variant::move(rhs_content) );
Chris@16 1984 }
Chris@16 1985 BOOST_CATCH (...)
Chris@16 1986 {
Chris@101 1987 assigner::construct_fallback();
Chris@16 1988
Chris@16 1989 // ...and rethrow:
Chris@16 1990 BOOST_RETHROW;
Chris@16 1991 }
Chris@16 1992 BOOST_CATCH_END
Chris@16 1993
Chris@16 1994 // In the event of success, indicate new content type:
Chris@101 1995 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
Chris@16 1996 }
Chris@101 1997
Chris@16 1998 template <typename RhsT>
Chris@16 1999 void assign_impl(
Chris@101 2000 RhsT& rhs_content
Chris@16 2001 , mpl::false_ // has_nothrow_copy
Chris@16 2002 , mpl::false_ // is_nothrow_move_constructible
Chris@16 2003 , mpl::false_ // has_fallback_type
Chris@101 2004 ) const
Chris@16 2005 {
Chris@101 2006 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
Chris@16 2007 }
Chris@16 2008
Chris@16 2009 public: // internal visitor interfaces
Chris@16 2010
Chris@16 2011 template <typename RhsT>
Chris@16 2012 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
Chris@101 2013 internal_visit(RhsT& rhs_content, int) const
Chris@16 2014 {
Chris@16 2015 typedef typename is_nothrow_move_constructible<RhsT>::type
Chris@16 2016 nothrow_move_constructor;
Chris@16 2017 typedef typename mpl::or_< // reduces compile-time
Chris@16 2018 nothrow_move_constructor
Chris@16 2019 , has_nothrow_copy<RhsT>
Chris@16 2020 >::type nothrow_copy;
Chris@16 2021
Chris@16 2022 assign_impl(
Chris@16 2023 rhs_content
Chris@16 2024 , nothrow_copy()
Chris@16 2025 , nothrow_move_constructor()
Chris@16 2026 , has_fallback_type_()
Chris@16 2027 );
Chris@16 2028
Chris@16 2029 BOOST_VARIANT_AUX_RETURN_VOID;
Chris@16 2030 }
Chris@16 2031
Chris@16 2032 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 2033 private:
Chris@16 2034 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 2035 move_assigner& operator= (move_assigner const&);
Chris@16 2036 #endif
Chris@16 2037 };
Chris@16 2038
Chris@16 2039 friend class move_assigner;
Chris@16 2040 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2041
Chris@16 2042 void variant_assign(const variant& rhs)
Chris@16 2043 {
Chris@16 2044 // If the contained types are EXACTLY the same...
Chris@16 2045 if (which_ == rhs.which_)
Chris@16 2046 {
Chris@16 2047 // ...then assign rhs's storage to lhs's content:
Chris@16 2048 detail::variant::assign_storage visitor(rhs.storage_.address());
Chris@16 2049 this->internal_apply_visitor(visitor);
Chris@16 2050 }
Chris@16 2051 else
Chris@16 2052 {
Chris@16 2053 // Otherwise, perform general (copy-based) variant assignment:
Chris@16 2054 assigner visitor(*this, rhs.which());
Chris@16 2055 rhs.internal_apply_visitor(visitor);
Chris@16 2056 }
Chris@16 2057 }
Chris@16 2058
Chris@16 2059 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2060 void variant_assign(variant&& rhs)
Chris@16 2061 {
Chris@16 2062 // If the contained types are EXACTLY the same...
Chris@16 2063 if (which_ == rhs.which_)
Chris@16 2064 {
Chris@16 2065 // ...then move rhs's storage to lhs's content:
Chris@16 2066 detail::variant::move_storage visitor(rhs.storage_.address());
Chris@16 2067 this->internal_apply_visitor(visitor);
Chris@16 2068 }
Chris@16 2069 else
Chris@16 2070 {
Chris@16 2071 // Otherwise, perform general (move-based) variant assignment:
Chris@16 2072 move_assigner visitor(*this, rhs.which());
Chris@16 2073 rhs.internal_apply_visitor(visitor);
Chris@16 2074 }
Chris@16 2075 }
Chris@16 2076 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2077
Chris@16 2078 private: // helpers, for modifiers (below)
Chris@16 2079
Chris@16 2080 template <typename T>
Chris@16 2081 void assign(const T& rhs)
Chris@16 2082 {
Chris@16 2083 // If direct T-to-T assignment is not possible...
Chris@16 2084 detail::variant::direct_assigner<T> direct_assign(rhs);
Chris@16 2085 if (this->apply_visitor(direct_assign) == false)
Chris@16 2086 {
Chris@16 2087 // ...then convert rhs to variant and assign:
Chris@16 2088 //
Chris@16 2089 // While potentially inefficient, the following construction of a
Chris@16 2090 // variant allows T as any type convertible to one of the bounded
Chris@16 2091 // types without excessive code redundancy.
Chris@16 2092 //
Chris@16 2093 variant temp(rhs);
Chris@16 2094 variant_assign( detail::variant::move(temp) );
Chris@16 2095 }
Chris@16 2096 }
Chris@16 2097
Chris@16 2098 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2099 template <typename T>
Chris@16 2100 void move_assign(T&& rhs)
Chris@16 2101 {
Chris@16 2102 // If direct T-to-T move assignment is not possible...
Chris@16 2103 detail::variant::direct_mover<T> direct_move(rhs);
Chris@16 2104 if (this->apply_visitor(direct_move) == false)
Chris@16 2105 {
Chris@16 2106 // ...then convert rhs to variant and assign:
Chris@16 2107 //
Chris@16 2108 // While potentially inefficient, the following construction of a
Chris@16 2109 // variant allows T as any type convertible to one of the bounded
Chris@16 2110 // types without excessive code redundancy.
Chris@16 2111 //
Chris@16 2112 variant temp( detail::variant::move(rhs) );
Chris@16 2113 variant_assign( detail::variant::move(temp) );
Chris@16 2114 }
Chris@16 2115 }
Chris@16 2116 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2117
Chris@16 2118 public: // modifiers
Chris@16 2119
Chris@16 2120 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2121 template <class T>
Chris@16 2122 typename boost::enable_if_c<boost::is_rvalue_reference<T&&>::value && !boost::is_const<T>::value, variant& >::type
Chris@101 2123 operator=(T&& rhs)
Chris@16 2124 {
Chris@16 2125 move_assign( detail::variant::move(rhs) );
Chris@16 2126 return *this;
Chris@16 2127 }
Chris@16 2128 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2129
Chris@16 2130 template <typename T>
Chris@16 2131 variant& operator=(const T& rhs)
Chris@16 2132 {
Chris@16 2133 assign(rhs);
Chris@16 2134 return *this;
Chris@16 2135 }
Chris@16 2136
Chris@16 2137 // [MSVC6 requires copy assign appear after templated operator=]
Chris@16 2138 variant& operator=(const variant& rhs)
Chris@16 2139 {
Chris@16 2140 variant_assign(rhs);
Chris@16 2141 return *this;
Chris@16 2142 }
Chris@16 2143
Chris@16 2144 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@101 2145 variant& operator=(variant&& rhs)
Chris@101 2146 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6)
Chris@101 2147 BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
Chris@101 2148 #endif
Chris@16 2149 {
Chris@16 2150 variant_assign( detail::variant::move(rhs) );
Chris@16 2151 return *this;
Chris@16 2152 }
Chris@16 2153 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 2154
Chris@16 2155 void swap(variant& rhs)
Chris@16 2156 {
Chris@16 2157 // If the contained types are the same...
Chris@16 2158 if (which() == rhs.which())
Chris@16 2159 {
Chris@16 2160 // ...then swap the values directly:
Chris@16 2161 detail::variant::swap_with<variant> visitor(rhs);
Chris@16 2162 this->apply_visitor(visitor);
Chris@16 2163 }
Chris@16 2164 else
Chris@16 2165 {
Chris@16 2166 // ...otherwise, perform general variant swap:
Chris@16 2167 variant tmp( detail::variant::move(rhs) );
Chris@16 2168 rhs = detail::variant::move(*this);
Chris@16 2169 *this = detail::variant::move(tmp);
Chris@16 2170 }
Chris@16 2171 }
Chris@16 2172
Chris@16 2173 public: // queries
Chris@16 2174
Chris@16 2175 //
Chris@16 2176 // NOTE: member which() defined above.
Chris@16 2177 //
Chris@16 2178
Chris@16 2179 bool empty() const BOOST_NOEXCEPT
Chris@16 2180 {
Chris@16 2181 return false;
Chris@16 2182 }
Chris@16 2183
Chris@101 2184 const boost::typeindex::type_info& type() const
Chris@16 2185 {
Chris@16 2186 detail::variant::reflect visitor;
Chris@16 2187 return this->apply_visitor(visitor);
Chris@16 2188 }
Chris@16 2189
Chris@16 2190 public: // prevent comparison with foreign types
Chris@16 2191
Chris@101 2192 // Obsolete. Remove.
Chris@16 2193 # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
Chris@16 2194 void
Chris@16 2195
Chris@16 2196 template <typename U>
Chris@101 2197 void operator==(const U&) const
Chris@16 2198 {
Chris@16 2199 BOOST_STATIC_ASSERT( false && sizeof(U) );
Chris@16 2200 }
Chris@16 2201
Chris@16 2202 template <typename U>
Chris@101 2203 void operator<(const U&) const
Chris@101 2204 {
Chris@101 2205 BOOST_STATIC_ASSERT( false && sizeof(U) );
Chris@101 2206 }
Chris@101 2207
Chris@101 2208 template <typename U>
Chris@101 2209 void operator!=(const U&) const
Chris@101 2210 {
Chris@101 2211 BOOST_STATIC_ASSERT( false && sizeof(U) );
Chris@101 2212 }
Chris@101 2213
Chris@101 2214 template <typename U>
Chris@101 2215 void operator>(const U&) const
Chris@101 2216 {
Chris@101 2217 BOOST_STATIC_ASSERT( false && sizeof(U) );
Chris@101 2218 }
Chris@101 2219
Chris@101 2220 template <typename U>
Chris@101 2221 void operator<=(const U&) const
Chris@101 2222 {
Chris@101 2223 BOOST_STATIC_ASSERT( false && sizeof(U) );
Chris@101 2224 }
Chris@101 2225
Chris@101 2226 template <typename U>
Chris@101 2227 void operator>=(const U&) const
Chris@16 2228 {
Chris@16 2229 BOOST_STATIC_ASSERT( false && sizeof(U) );
Chris@16 2230 }
Chris@16 2231
Chris@16 2232 public: // comparison operators
Chris@16 2233
Chris@16 2234 // [MSVC6 requires these operators appear after template operators]
Chris@16 2235
Chris@16 2236 bool operator==(const variant& rhs) const
Chris@16 2237 {
Chris@16 2238 if (this->which() != rhs.which())
Chris@16 2239 return false;
Chris@16 2240
Chris@16 2241 detail::variant::comparer<
Chris@16 2242 variant, detail::variant::equal_comp
Chris@16 2243 > visitor(*this);
Chris@16 2244 return rhs.apply_visitor(visitor);
Chris@16 2245 }
Chris@16 2246
Chris@16 2247 bool operator<(const variant& rhs) const
Chris@16 2248 {
Chris@16 2249 //
Chris@16 2250 // Dirk Schreib suggested this collating order.
Chris@16 2251 //
Chris@16 2252
Chris@16 2253 if (this->which() != rhs.which())
Chris@16 2254 return this->which() < rhs.which();
Chris@16 2255
Chris@16 2256 detail::variant::comparer<
Chris@16 2257 variant, detail::variant::less_comp
Chris@16 2258 > visitor(*this);
Chris@16 2259 return rhs.apply_visitor(visitor);
Chris@16 2260 }
Chris@16 2261
Chris@101 2262 ///////////////////////////////////////////////////////////////////////////////
Chris@101 2263 // comparison operators != > <= >=
Chris@101 2264 inline bool operator!=(const variant& rhs) const
Chris@101 2265 {
Chris@101 2266 return !(*this == rhs);
Chris@101 2267 }
Chris@101 2268
Chris@101 2269 inline bool operator>(const variant& rhs) const
Chris@101 2270 {
Chris@101 2271 return rhs < *this;
Chris@101 2272 }
Chris@101 2273
Chris@101 2274 inline bool operator<=(const variant& rhs) const
Chris@101 2275 {
Chris@101 2276 return !(*this > rhs);
Chris@101 2277 }
Chris@101 2278
Chris@101 2279 inline bool operator>=(const variant& rhs) const
Chris@101 2280 {
Chris@101 2281 return !(*this < rhs);
Chris@101 2282 }
Chris@101 2283
Chris@16 2284 // helpers, for visitation support (below) -- private when possible
Chris@16 2285 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
Chris@16 2286
Chris@16 2287 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
Chris@16 2288 friend class variant;
Chris@16 2289
Chris@16 2290 private:
Chris@16 2291
Chris@16 2292 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
Chris@16 2293
Chris@16 2294 public:
Chris@16 2295
Chris@16 2296 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
Chris@16 2297
Chris@16 2298 template <typename Visitor, typename VoidPtrCV>
Chris@16 2299 static
Chris@16 2300 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
Chris@16 2301 typename Visitor::result_type
Chris@16 2302 )
Chris@16 2303 internal_apply_visitor_impl(
Chris@16 2304 int internal_which
Chris@16 2305 , int logical_which
Chris@16 2306 , Visitor& visitor
Chris@16 2307 , VoidPtrCV storage
Chris@16 2308 )
Chris@16 2309 {
Chris@16 2310 typedef mpl::int_<0> first_which;
Chris@16 2311 typedef typename mpl::begin<internal_types>::type first_it;
Chris@16 2312 typedef typename mpl::end<internal_types>::type last_it;
Chris@16 2313
Chris@16 2314 typedef detail::variant::visitation_impl_step<
Chris@16 2315 first_it, last_it
Chris@16 2316 > first_step;
Chris@16 2317
Chris@16 2318 return detail::variant::visitation_impl(
Chris@16 2319 internal_which, logical_which
Chris@16 2320 , visitor, storage, mpl::false_()
Chris@16 2321 , never_uses_backup_flag()
Chris@16 2322 , static_cast<first_which*>(0), static_cast<first_step*>(0)
Chris@16 2323 );
Chris@16 2324 }
Chris@16 2325
Chris@16 2326 template <typename Visitor>
Chris@16 2327 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
Chris@16 2328 typename Visitor::result_type
Chris@16 2329 )
Chris@16 2330 internal_apply_visitor(Visitor& visitor)
Chris@16 2331 {
Chris@16 2332 return internal_apply_visitor_impl(
Chris@16 2333 which_, which(), visitor, storage_.address()
Chris@16 2334 );
Chris@16 2335 }
Chris@16 2336
Chris@16 2337 template <typename Visitor>
Chris@16 2338 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
Chris@16 2339 typename Visitor::result_type
Chris@16 2340 )
Chris@16 2341 internal_apply_visitor(Visitor& visitor) const
Chris@16 2342 {
Chris@16 2343 return internal_apply_visitor_impl(
Chris@16 2344 which_, which(), visitor, storage_.address()
Chris@16 2345 );
Chris@16 2346 }
Chris@16 2347
Chris@16 2348 public: // visitation support
Chris@16 2349
Chris@16 2350 template <typename Visitor>
Chris@16 2351 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
Chris@16 2352 typename Visitor::result_type
Chris@16 2353 )
Chris@16 2354 apply_visitor(Visitor& visitor)
Chris@16 2355 {
Chris@16 2356 detail::variant::invoke_visitor<Visitor> invoker(visitor);
Chris@16 2357 return this->internal_apply_visitor(invoker);
Chris@16 2358 }
Chris@16 2359
Chris@16 2360 template <typename Visitor>
Chris@16 2361 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
Chris@16 2362 typename Visitor::result_type
Chris@16 2363 )
Chris@16 2364 apply_visitor(Visitor& visitor) const
Chris@16 2365 {
Chris@16 2366 detail::variant::invoke_visitor<Visitor> invoker(visitor);
Chris@16 2367 return this->internal_apply_visitor(invoker);
Chris@16 2368 }
Chris@16 2369
Chris@16 2370 }; // class variant
Chris@16 2371
Chris@16 2372 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2373 // metafunction make_variant_over
Chris@16 2374 //
Chris@16 2375 // See docs and boost/variant/variant_fwd.hpp for more information.
Chris@16 2376 //
Chris@16 2377 template <typename Types>
Chris@16 2378 struct make_variant_over
Chris@16 2379 {
Chris@16 2380 private: // precondition assertions
Chris@16 2381
Chris@16 2382 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
Chris@16 2383
Chris@16 2384 public: // metafunction result
Chris@16 2385
Chris@16 2386 typedef variant<
Chris@16 2387 detail::variant::over_sequence< Types >
Chris@16 2388 > type;
Chris@16 2389
Chris@16 2390 };
Chris@16 2391
Chris@101 2392
Chris@16 2393 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2394 // function template swap
Chris@16 2395 //
Chris@16 2396 // Swaps two variants of the same type (i.e., identical specification).
Chris@16 2397 //
Chris@16 2398 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
Chris@16 2399 inline void swap(
Chris@16 2400 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
Chris@16 2401 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
Chris@16 2402 )
Chris@16 2403 {
Chris@16 2404 lhs.swap(rhs);
Chris@16 2405 }
Chris@16 2406
Chris@16 2407 } // namespace boost
Chris@16 2408
Chris@16 2409 // implementation additions
Chris@16 2410
Chris@16 2411 #if !defined(BOOST_NO_IOSTREAM)
Chris@16 2412 #include "boost/variant/detail/variant_io.hpp"
Chris@16 2413 #endif // BOOST_NO_IOSTREAM
Chris@16 2414
Chris@16 2415 #endif // BOOST_VARIANT_VARIANT_HPP