1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/epoc32/include/stdapis/boost/variant.hpp Wed Mar 31 12:27:01 2010 +0100
1.3 @@ -0,0 +1,1833 @@
1.4 +//-----------------------------------------------------------------------------
1.5 +// boost variant/variant.hpp header file
1.6 +// See http://www.boost.org for updates, documentation, and revision history.
1.7 +//-----------------------------------------------------------------------------
1.8 +//
1.9 +// Copyright (c) 2002-2003
1.10 +// Eric Friedman, Itay Maman
1.11 +//
1.12 +// Distributed under the Boost Software License, Version 1.0. (See
1.13 +// accompanying file LICENSE_1_0.txt or copy at
1.14 +// http://www.boost.org/LICENSE_1_0.txt)
1.15 +/*
1.16 + * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
1.17 +*/
1.18 +#ifndef BOOST_VARIANT_VARIANT_HPP
1.19 +#define BOOST_VARIANT_VARIANT_HPP
1.20 +
1.21 +#include <cstddef> // for std::size_t
1.22 +#include <new> // for placement new
1.23 +#ifdef __SYMBIAN32__
1.24 +#include <string>
1.25 +#endif
1.26 +#include <typeinfo> // for typeid, std::type_info
1.27 +
1.28 +#include "boost/variant/detail/config.hpp"
1.29 +#include "boost/mpl/aux_/config/eti.hpp"
1.30 +#include "boost/mpl/aux_/value_wknd.hpp"
1.31 +
1.32 +#include "boost/variant/variant_fwd.hpp"
1.33 +#include "boost/variant/detail/backup_holder.hpp"
1.34 +#include "boost/variant/detail/enable_recursive_fwd.hpp"
1.35 +#include "boost/variant/detail/forced_return.hpp"
1.36 +#include "boost/variant/detail/initializer.hpp"
1.37 +#include "boost/variant/detail/make_variant_list.hpp"
1.38 +#include "boost/variant/detail/over_sequence.hpp"
1.39 +#include "boost/variant/detail/visitation_impl.hpp"
1.40 +
1.41 +#include "boost/variant/detail/generic_result_type.hpp"
1.42 +#include "boost/variant/detail/has_nothrow_move.hpp"
1.43 +#include "boost/variant/detail/move.hpp"
1.44 +
1.45 +#include "boost/detail/reference_content.hpp"
1.46 +#include "boost/aligned_storage.hpp"
1.47 +#include "boost/blank.hpp"
1.48 +#include "boost/static_assert.hpp"
1.49 +#include "boost/preprocessor/cat.hpp"
1.50 +#include "boost/preprocessor/repeat.hpp"
1.51 +#include "boost/type_traits/alignment_of.hpp"
1.52 +#include "boost/type_traits/add_const.hpp"
1.53 +#include "boost/type_traits/has_nothrow_constructor.hpp"
1.54 +#include "boost/type_traits/has_nothrow_copy.hpp"
1.55 +#include "boost/type_traits/is_const.hpp"
1.56 +#include "boost/type_traits/is_same.hpp"
1.57 +#include "boost/utility/enable_if.hpp"
1.58 +#include "boost/variant/recursive_wrapper_fwd.hpp"
1.59 +#include "boost/variant/static_visitor.hpp"
1.60 +
1.61 +#include "boost/mpl/eval_if.hpp"
1.62 +#include "boost/mpl/begin_end.hpp"
1.63 +#include "boost/mpl/bool.hpp"
1.64 +#include "boost/mpl/empty.hpp"
1.65 +#include "boost/mpl/find_if.hpp"
1.66 +#include "boost/mpl/front.hpp"
1.67 +#include "boost/mpl/identity.hpp"
1.68 +#include "boost/mpl/if.hpp"
1.69 +#include "boost/mpl/int.hpp"
1.70 +#include "boost/mpl/is_sequence.hpp"
1.71 +#include "boost/mpl/iterator_range.hpp"
1.72 +#include "boost/mpl/iter_fold_if.hpp"
1.73 +#include "boost/mpl/logical.hpp"
1.74 +#include "boost/mpl/max_element.hpp"
1.75 +#include "boost/mpl/next.hpp"
1.76 +#include "boost/mpl/deref.hpp"
1.77 +#include "boost/mpl/pair.hpp"
1.78 +#include "boost/mpl/protect.hpp"
1.79 +#include "boost/mpl/push_front.hpp"
1.80 +#include "boost/mpl/same_as.hpp"
1.81 +#include "boost/mpl/size_t.hpp"
1.82 +#include "boost/mpl/sizeof.hpp"
1.83 +#include "boost/mpl/transform.hpp"
1.84 +#include "boost/mpl/assert.hpp"
1.85 +
1.86 +///////////////////////////////////////////////////////////////////////////////
1.87 +// Implementation Macros:
1.88 +//
1.89 +// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
1.90 +// Defined in boost/variant/detail/visitation_impl.hpp.
1.91 +//
1.92 +// BOOST_VARIANT_MINIMIZE_SIZE
1.93 +// When #defined, implementation employs all known means to minimize the
1.94 +// size of variant obje cts. However, often unsuccessful due to alignment
1.95 +// issues, and potentially harmful to runtime speed, so not enabled by
1.96 +// default. (TODO: Investigate further.)
1.97 +
1.98 +#if defined(BOOST_VARIANT_MINIMIZE_SIZE)
1.99 +# include <climits> // for SCHAR_MAX
1.100 +# include "boost/mpl/eval_if.hpp"
1.101 +# include "boost/mpl/equal_to.hpp"
1.102 +# include "boost/mpl/identity.hpp"
1.103 +# include "boost/mpl/int.hpp"
1.104 +# include "boost/mpl/if.hpp"
1.105 +# include "boost/mpl/less.hpp"
1.106 +# include "boost/mpl/long.hpp"
1.107 +# include "boost/mpl/O1_size.hpp"
1.108 +#endif
1.109 +
1.110 +
1.111 +namespace boost {
1.112 +
1.113 +namespace detail { namespace variant {
1.114 +
1.115 +///////////////////////////////////////////////////////////////////////////////
1.116 +// (detail) metafunction max_value
1.117 +//
1.118 +// Finds the maximum value of the unary metafunction F over Sequence.
1.119 +//
1.120 +template <typename Sequence, typename F>
1.121 +struct max_value
1.122 +{
1.123 +private: // helpers, for metafunction result (below)
1.124 +
1.125 + typedef typename mpl::transform1<Sequence, F>::type transformed_;
1.126 + typedef typename mpl::max_element<transformed_
1.127 +
1.128 + >::type max_it;
1.129 +
1.130 +public: // metafunction result
1.131 +
1.132 + typedef typename mpl::deref<max_it>::type
1.133 + type;
1.134 +
1.135 +};
1.136 +
1.137 +///////////////////////////////////////////////////////////////////////////////
1.138 +// (detail) metafunction find_fallback_type
1.139 +//
1.140 +// Provides a fallback (i.e., nothrow default-constructible) type from the
1.141 +// specified sequence, or no_fallback_type if not found.
1.142 +//
1.143 +// This implementation is designed to prefer boost::blank over other potential
1.144 +// fallback types, regardless of its position in the specified sequence.
1.145 +//
1.146 +
1.147 +class no_fallback_type;
1.148 +
1.149 +struct find_fallback_type_pred
1.150 +{
1.151 + template <typename Iterator>
1.152 + struct apply
1.153 + {
1.154 + private:
1.155 + typedef typename mpl::deref<Iterator>::type t_;
1.156 +
1.157 + public:
1.158 + typedef mpl::not_< has_nothrow_constructor<t_> > type;
1.159 + };
1.160 +};
1.161 +
1.162 +template <typename Types>
1.163 +struct find_fallback_type
1.164 +{
1.165 +private: // helpers, for metafunction result (below)
1.166 +
1.167 + typedef typename mpl::end<Types>::type end_it;
1.168 +
1.169 + // [Find the first suitable fallback type...]
1.170 +
1.171 + typedef typename mpl::iter_fold_if<
1.172 + Types
1.173 + , mpl::int_<0>, mpl::protect< mpl::next<> >
1.174 + , mpl::protect< find_fallback_type_pred >
1.175 + >::type first_result_;
1.176 +
1.177 + typedef typename first_result_::first first_result_index;
1.178 + typedef typename first_result_::second first_result_it;
1.179 +
1.180 + // [...now search the rest of the sequence for boost::blank...]
1.181 +
1.182 + typedef typename mpl::iter_fold_if<
1.183 + mpl::iterator_range< first_result_it,end_it >
1.184 + , first_result_index, mpl::protect< mpl::next<> >
1.185 + , mpl::protect< mpl::not_same_as<boost::blank> >
1.186 + >::type second_result_;
1.187 +
1.188 + typedef typename second_result_::second second_result_it;
1.189 +
1.190 +public: // metafunction result
1.191 +
1.192 + // [...and return the results of the search:]
1.193 + typedef typename mpl::eval_if<
1.194 + is_same< second_result_it,end_it >
1.195 + , mpl::if_<
1.196 + is_same< first_result_it,end_it >
1.197 + , mpl::pair< no_fallback_type,no_fallback_type >
1.198 + , first_result_
1.199 + >
1.200 + , mpl::identity< second_result_ >
1.201 + >::type type;
1.202 +
1.203 +};
1.204 +
1.205 +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
1.206 +
1.207 +template<>
1.208 +struct find_fallback_type<int>
1.209 +{
1.210 + typedef mpl::pair< no_fallback_type,no_fallback_type > type;
1.211 +};
1.212 +
1.213 +#endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
1.214 +
1.215 +///////////////////////////////////////////////////////////////////////////////
1.216 +// (detail) metafunction make_storage
1.217 +//
1.218 +// Provides an aligned storage type capable of holding any of the types
1.219 +// specified in the given type-sequence.
1.220 +//
1.221 +
1.222 +template <typename Types, typename NeverUsesBackupFlag>
1.223 +struct make_storage
1.224 +{
1.225 +private: // helpers, for metafunction result (below)
1.226 +
1.227 + typedef typename mpl::eval_if<
1.228 + NeverUsesBackupFlag
1.229 + , mpl::identity< Types >
1.230 + , mpl::push_front<
1.231 + Types, backup_holder<void*>
1.232 + >
1.233 + >::type types;
1.234 +
1.235 + typedef typename max_value<
1.236 + types, mpl::sizeof_<mpl::_1>
1.237 + >::type max_size;
1.238 +
1.239 +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
1.240 +
1.241 + typedef typename max_value<
1.242 + types, alignment_of<mpl::_1>
1.243 + >::type max_alignment;
1.244 +
1.245 +#else // borland
1.246 +
1.247 + // temporary workaround -- use maximal alignment
1.248 + typedef mpl::size_t< -1 > max_alignment;
1.249 +
1.250 +#endif // borland workaround
1.251 +
1.252 +public: // metafunction result
1.253 +
1.254 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1.255 +
1.256 + typedef ::boost::aligned_storage<
1.257 + BOOST_MPL_AUX_VALUE_WKND(max_size)::value
1.258 + , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
1.259 + > type;
1.260 +
1.261 +#else // MSVC7 and below
1.262 +
1.263 + BOOST_STATIC_CONSTANT(std::size_t, msvc_max_size_c = max_size::value);
1.264 + BOOST_STATIC_CONSTANT(std::size_t, msvc_max_alignment_c = max_alignment::value);
1.265 +
1.266 + typedef ::boost::aligned_storage<
1.267 + msvc_max_size_c
1.268 + , msvc_max_alignment_c
1.269 + > type;
1.270 +
1.271 +#endif // MSVC workaround
1.272 +
1.273 +};
1.274 +
1.275 +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
1.276 +
1.277 +template<>
1.278 +struct make_storage<int,int>
1.279 +{
1.280 + typedef int type;
1.281 +};
1.282 +
1.283 +#endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
1.284 +
1.285 +///////////////////////////////////////////////////////////////////////////////
1.286 +// (detail) class destroyer
1.287 +//
1.288 +// Internal visitor that destroys the value it visits.
1.289 +//
1.290 +struct destroyer
1.291 + : public static_visitor<>
1.292 +{
1.293 +public: // visitor interfaces
1.294 +
1.295 + template <typename T>
1.296 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.297 + internal_visit(T& operand, int) const
1.298 + {
1.299 + operand.~T();
1.300 +
1.301 +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
1.302 + operand; // suppresses warnings
1.303 +#endif
1.304 +
1.305 + BOOST_VARIANT_AUX_RETURN_VOID;
1.306 + }
1.307 +
1.308 +};
1.309 +
1.310 +///////////////////////////////////////////////////////////////////////////////
1.311 +// (detail) class template known_get
1.312 +//
1.313 +// Visitor that returns a reference to content of the specified type.
1.314 +//
1.315 +// Precondition: visited variant MUST contain logical content of type T.
1.316 +//
1.317 +template <typename T>
1.318 +class known_get
1.319 + : public static_visitor<T&>
1.320 +{
1.321 +
1.322 +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
1.323 +
1.324 +public: // visitor interface
1.325 +
1.326 + T& operator()(T& operand) const
1.327 + {
1.328 + return operand;
1.329 + }
1.330 +
1.331 + template <typename U>
1.332 + T& operator()(U&) const
1.333 + {
1.334 + // logical error to be here: see precondition above
1.335 + BOOST_ASSERT(false);
1.336 + return ::boost::detail::variant::forced_return< T& >();
1.337 + }
1.338 +
1.339 +#else // MSVC6
1.340 +
1.341 +private: // helpers, for visitor interface (below)
1.342 +
1.343 + T& execute(T& operand, mpl::true_) const
1.344 + {
1.345 + return operand;
1.346 + }
1.347 +
1.348 + template <typename U>
1.349 + T& execute(U& operand, mpl::false_) const
1.350 + {
1.351 + // logical error to be here: see precondition above
1.352 + BOOST_ASSERT(false);
1.353 + return ::boost::detail::variant::forced_return< T& >();
1.354 + }
1.355 +
1.356 +public: // visitor interface
1.357 +
1.358 + template <typename U>
1.359 + T& operator()(U& operand) const
1.360 + {
1.361 + typedef typename is_same< U,T >::type
1.362 + U_is_T;
1.363 +
1.364 + return execute(operand, U_is_T());
1.365 + }
1.366 +
1.367 +#endif // MSVC6 workaround
1.368 +
1.369 +};
1.370 +
1.371 +///////////////////////////////////////////////////////////////////////////////
1.372 +// (detail) class copy_into
1.373 +//
1.374 +// Internal visitor that copies the value it visits into the given buffer.
1.375 +//
1.376 +class copy_into
1.377 + : public static_visitor<>
1.378 +{
1.379 +private: // representation
1.380 +
1.381 + void* storage_;
1.382 +
1.383 +public: // structors
1.384 +
1.385 + explicit copy_into(void* storage)
1.386 + : storage_(storage)
1.387 + {
1.388 + }
1.389 +
1.390 +public: // internal visitor interface
1.391 +
1.392 + template <typename T>
1.393 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.394 + internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1.395 + {
1.396 + new(storage_) T( operand.get() );
1.397 + BOOST_VARIANT_AUX_RETURN_VOID;
1.398 + }
1.399 +
1.400 + template <typename T>
1.401 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.402 + internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1.403 + {
1.404 + new(storage_) T( operand.get() );
1.405 + BOOST_VARIANT_AUX_RETURN_VOID;
1.406 + }
1.407 +
1.408 + template <typename T>
1.409 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.410 + internal_visit(const T& operand, int) const
1.411 + {
1.412 + new(storage_) T(operand);
1.413 + BOOST_VARIANT_AUX_RETURN_VOID;
1.414 + }
1.415 +
1.416 +};
1.417 +
1.418 +///////////////////////////////////////////////////////////////////////////////
1.419 +// (detail) class assign_storage
1.420 +//
1.421 +// Internal visitor that assigns the given storage (which must be a
1.422 +// constructed value of the same type) to the value it visits.
1.423 +//
1.424 +struct assign_storage
1.425 + : public static_visitor<>
1.426 +{
1.427 +private: // representation
1.428 +
1.429 + const void* rhs_storage_;
1.430 +
1.431 +public: // structors
1.432 +
1.433 + explicit assign_storage(const void* rhs_storage)
1.434 + : rhs_storage_(rhs_storage)
1.435 + {
1.436 + }
1.437 +
1.438 +public: // internal visitor interfaces
1.439 +
1.440 + template <typename T>
1.441 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.442 + internal_visit(backup_holder<T>& lhs_content, long) const
1.443 + {
1.444 + lhs_content.get()
1.445 + = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
1.446 + BOOST_VARIANT_AUX_RETURN_VOID;
1.447 + }
1.448 +
1.449 + template <typename T>
1.450 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.451 + internal_visit(const backup_holder<T>& lhs_content, long) const
1.452 + {
1.453 + lhs_content.get()
1.454 + = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
1.455 + BOOST_VARIANT_AUX_RETURN_VOID;
1.456 + }
1.457 +
1.458 + template <typename T>
1.459 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.460 + internal_visit(T& lhs_content, int) const
1.461 + {
1.462 + // NOTE TO USER :
1.463 + // Compile error here indicates one of variant's bounded types does
1.464 + // not meet the requirements of the Assignable concept. Thus,
1.465 + // variant is not Assignable.
1.466 + //
1.467 + // Hint: Are any of the bounded types const-qualified or references?
1.468 + //
1.469 + lhs_content = *static_cast< const T* >(rhs_storage_);
1.470 + BOOST_VARIANT_AUX_RETURN_VOID;
1.471 + }
1.472 +
1.473 +};
1.474 +
1.475 +///////////////////////////////////////////////////////////////////////////////
1.476 +// (detail) class direct_assigner
1.477 +//
1.478 +// Generic static visitor that: if and only if the visited value is of the
1.479 +// specified type, assigns the given value to the visited value and returns
1.480 +// true; else returns false.
1.481 +//
1.482 +template <typename T>
1.483 +class direct_assigner
1.484 + : public static_visitor<bool>
1.485 +{
1.486 +private: // representation
1.487 +
1.488 + T& rhs_;
1.489 +
1.490 +public: // structors
1.491 +
1.492 + explicit direct_assigner(T& rhs)
1.493 + : rhs_(rhs)
1.494 + {
1.495 + }
1.496 +
1.497 +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
1.498 +
1.499 +public: // visitor interface
1.500 +
1.501 + bool operator()(T& lhs)
1.502 + {
1.503 + lhs = rhs_;
1.504 + return true;
1.505 + }
1.506 +
1.507 + template <typename U>
1.508 + bool operator()(U&)
1.509 + {
1.510 + return false;
1.511 + }
1.512 +
1.513 +#else // MSVC6
1.514 +
1.515 +private: // helpers, for visitor interface (below)
1.516 +
1.517 + bool execute(T& lhs, mpl::true_)
1.518 + {
1.519 + lhs = rhs_;
1.520 + return true;
1.521 + }
1.522 +
1.523 + template <typename U>
1.524 + bool execute(U&, mpl::false_)
1.525 + {
1.526 + return false;
1.527 + }
1.528 +
1.529 +public: // visitor interface
1.530 +
1.531 + template <typename U>
1.532 + bool operator()(U& lhs)
1.533 + {
1.534 + typedef typename is_same<U,T>::type U_is_T;
1.535 + return execute(lhs, U_is_T());
1.536 + }
1.537 +
1.538 +#endif // MSVC6 workaround
1.539 +
1.540 +};
1.541 +
1.542 +///////////////////////////////////////////////////////////////////////////////
1.543 +// (detail) class backup_assigner
1.544 +//
1.545 +// Internal visitor that "assigns" the given value to the visited value,
1.546 +// using backup to recover if the destroy-copy sequence fails.
1.547 +//
1.548 +// NOTE: This needs to be a friend of variant, as it needs access to
1.549 +// indicate_which, indicate_backup_which, etc.
1.550 +//
1.551 +template <typename Variant, typename RhsT>
1.552 +class backup_assigner
1.553 + : public static_visitor<>
1.554 +{
1.555 +private: // representation
1.556 +
1.557 + Variant& lhs_;
1.558 + int rhs_which_;
1.559 + const RhsT& rhs_content_;
1.560 +
1.561 +public: // structors
1.562 +
1.563 + backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
1.564 + : lhs_(lhs)
1.565 + , rhs_which_(rhs_which)
1.566 + , rhs_content_(rhs_content)
1.567 + {
1.568 + }
1.569 +
1.570 +private: // helpers, for visitor interface (below)
1.571 +
1.572 + template <typename LhsT>
1.573 + void backup_assign_impl(
1.574 + LhsT& lhs_content
1.575 + , mpl::true_// has_nothrow_move
1.576 + )
1.577 + {
1.578 + // Move lhs content to backup...
1.579 + LhsT backup_lhs_content(
1.580 + ::boost::detail::variant::move(lhs_content)
1.581 + ); // nothrow
1.582 +
1.583 + // ...destroy lhs content...
1.584 + lhs_content.~LhsT(); // nothrow
1.585 +
1.586 + try
1.587 + {
1.588 + // ...and attempt to copy rhs content into lhs storage:
1.589 + new(lhs_.storage_.address()) RhsT(rhs_content_);
1.590 + }
1.591 + catch (...)
1.592 + {
1.593 + // In case of failure, restore backup content to lhs storage...
1.594 + new(lhs_.storage_.address())
1.595 + LhsT(
1.596 + ::boost::detail::variant::move(backup_lhs_content)
1.597 + ); // nothrow
1.598 +
1.599 + // ...and rethrow:
1.600 + throw;
1.601 + }
1.602 +
1.603 + // In case of success, indicate new content type:
1.604 + lhs_.indicate_which(rhs_which_); // nothrow
1.605 + }
1.606 +
1.607 + template <typename LhsT>
1.608 + void backup_assign_impl(
1.609 + LhsT& lhs_content
1.610 + , mpl::false_// has_nothrow_move
1.611 + )
1.612 + {
1.613 + // Backup lhs content...
1.614 + LhsT* backup_lhs_ptr = new LhsT(lhs_content);
1.615 +
1.616 + // ...destroy lhs content...
1.617 + lhs_content.~LhsT(); // nothrow
1.618 +
1.619 + try
1.620 + {
1.621 + // ...and attempt to copy rhs content into lhs storage:
1.622 + new(lhs_.storage_.address()) RhsT(rhs_content_);
1.623 + }
1.624 + catch (...)
1.625 + {
1.626 + // In case of failure, copy backup pointer to lhs storage...
1.627 + new(lhs_.storage_.address())
1.628 + backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
1.629 +
1.630 + // ...indicate now using backup...
1.631 + lhs_.indicate_backup_which( lhs_.which() ); // nothrow
1.632 +
1.633 + // ...and rethrow:
1.634 + throw;
1.635 + }
1.636 +
1.637 + // In case of success, indicate new content type...
1.638 + lhs_.indicate_which(rhs_which_); // nothrow
1.639 +
1.640 + // ...and delete backup:
1.641 + delete backup_lhs_ptr; // nothrow
1.642 + }
1.643 +
1.644 +public: // visitor interface
1.645 +
1.646 + template <typename LhsT>
1.647 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.648 + internal_visit(LhsT& lhs_content, int)
1.649 + {
1.650 + typedef typename has_nothrow_move_constructor<LhsT>::type
1.651 + nothrow_move;
1.652 +
1.653 + backup_assign_impl( lhs_content, nothrow_move() );
1.654 +
1.655 + BOOST_VARIANT_AUX_RETURN_VOID;
1.656 + }
1.657 +
1.658 +};
1.659 +
1.660 +///////////////////////////////////////////////////////////////////////////////
1.661 +// (detail) class swap_with
1.662 +//
1.663 +// Visitor that swaps visited value with content of given variant.
1.664 +//
1.665 +// Precondition: Given variant MUST have same logical type as visited value.
1.666 +//
1.667 +template <typename Variant>
1.668 +struct swap_with
1.669 + : public static_visitor<>
1.670 +{
1.671 +private: // representation
1.672 +
1.673 + Variant& toswap_;
1.674 +
1.675 +public: // structors
1.676 +
1.677 + explicit swap_with(Variant& toswap)
1.678 + : toswap_(toswap)
1.679 + {
1.680 + }
1.681 +
1.682 +public: // internal visitor interfaces
1.683 +
1.684 + template <typename T>
1.685 + void operator()(T& operand) const
1.686 + {
1.687 + // Since the precondition ensures types are same, get T...
1.688 + known_get<T> getter;
1.689 + T& other = toswap_.apply_visitor(getter);
1.690 +
1.691 + // ...and swap:
1.692 + ::boost::detail::variant::move_swap( operand, other );
1.693 + }
1.694 +
1.695 +};
1.696 +
1.697 +///////////////////////////////////////////////////////////////////////////////
1.698 +// (detail) class reflect
1.699 +//
1.700 +// Generic static visitor that performs a typeid on the value it visits.
1.701 +//
1.702 +class reflect
1.703 + : public static_visitor<const std::type_info&>
1.704 +{
1.705 +public: // visitor interfaces
1.706 +
1.707 + template <typename T>
1.708 + const std::type_info& operator()(const T&) const
1.709 + {
1.710 + return typeid(T);
1.711 + }
1.712 +
1.713 +};
1.714 +
1.715 +///////////////////////////////////////////////////////////////////////////////
1.716 +// (detail) class comparer
1.717 +//
1.718 +// Generic static visitor that compares the content of the given lhs variant
1.719 +// with the visited rhs content using Comp.
1.720 +//
1.721 +// Precondition: lhs.which() == rhs.which()
1.722 +//
1.723 +template <typename Variant, typename Comp>
1.724 +class comparer
1.725 + : public static_visitor<bool>
1.726 +{
1.727 +private: // representation
1.728 +
1.729 + const Variant& lhs_;
1.730 +
1.731 +public: // structors
1.732 +
1.733 + explicit comparer(const Variant& lhs)
1.734 + : lhs_(lhs)
1.735 + {
1.736 + }
1.737 +
1.738 +public: // visitor interfaces
1.739 +
1.740 + template <typename T>
1.741 + bool operator()(const T& rhs_content) const
1.742 + {
1.743 + // Since the precondition ensures lhs and rhs types are same, get T...
1.744 + known_get<const T> getter;
1.745 + const T& lhs_content = lhs_.apply_visitor(getter);
1.746 +
1.747 + // ...and compare lhs and rhs contents:
1.748 + return Comp()(lhs_content, rhs_content);
1.749 + }
1.750 +
1.751 +};
1.752 +
1.753 +///////////////////////////////////////////////////////////////////////////////
1.754 +// (detail) class equal_comp
1.755 +//
1.756 +// Generic function object compares lhs with rhs using operator==.
1.757 +//
1.758 +struct equal_comp
1.759 +{
1.760 + template <typename T>
1.761 + bool operator()(const T& lhs, const T& rhs) const
1.762 + {
1.763 + return lhs == rhs;
1.764 + }
1.765 +};
1.766 +
1.767 +///////////////////////////////////////////////////////////////////////////////
1.768 +// (detail) class less_comp
1.769 +//
1.770 +// Generic function object compares lhs with rhs using operator<.
1.771 +//
1.772 +struct less_comp
1.773 +{
1.774 + template <typename T>
1.775 + bool operator()(const T& lhs, const T& rhs) const
1.776 + {
1.777 + return lhs < rhs;
1.778 + }
1.779 +};
1.780 +
1.781 +///////////////////////////////////////////////////////////////////////////////
1.782 +// (detail) class template invoke_visitor
1.783 +//
1.784 +// Internal visitor that invokes the given visitor using:
1.785 +// * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
1.786 +// * for all other values, the value itself.
1.787 +//
1.788 +template <typename Visitor>
1.789 +class invoke_visitor
1.790 +{
1.791 +private: // representation
1.792 +
1.793 + Visitor& visitor_;
1.794 +
1.795 +public: // visitor typedefs
1.796 +
1.797 + typedef typename Visitor::result_type
1.798 + result_type;
1.799 +
1.800 +public: // structors
1.801 +
1.802 + explicit invoke_visitor(Visitor& visitor)
1.803 + : visitor_(visitor)
1.804 + {
1.805 + }
1.806 +
1.807 +#if !defined(BOOST_NO_VOID_RETURNS)
1.808 +
1.809 +public: // internal visitor interfaces
1.810 +
1.811 + template <typename T>
1.812 + result_type internal_visit(T& operand, int)
1.813 + {
1.814 + return visitor_(operand);
1.815 + }
1.816 +
1.817 +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1.818 + template <typename T>
1.819 + result_type internal_visit(const T& operand, int)
1.820 + {
1.821 + return visitor_(operand);
1.822 + }
1.823 +# endif
1.824 +
1.825 +#else // defined(BOOST_NO_VOID_RETURNS)
1.826 +
1.827 +private: // helpers, for internal visitor interfaces (below)
1.828 +
1.829 + template <typename T>
1.830 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.831 + visit_impl(T& operand, mpl::false_)
1.832 + {
1.833 + return visitor_(operand);
1.834 + }
1.835 +
1.836 + template <typename T>
1.837 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.838 + visit_impl(T& operand, mpl::true_)
1.839 + {
1.840 + visitor_(operand);
1.841 + BOOST_VARIANT_AUX_RETURN_VOID;
1.842 + }
1.843 +
1.844 +public: // internal visitor interfaces
1.845 +
1.846 + template <typename T>
1.847 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.848 + internal_visit(T& operand, int)
1.849 + {
1.850 + typedef typename is_same<result_type, void>::type
1.851 + has_void_result_type;
1.852 +
1.853 + return visit_impl(operand, has_void_result_type());
1.854 + }
1.855 +
1.856 +#endif // BOOST_NO_VOID_RETURNS) workaround
1.857 +
1.858 +public: // internal visitor interfaces, cont.
1.859 +
1.860 + template <typename T>
1.861 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.862 + internal_visit(boost::recursive_wrapper<T>& operand, long)
1.863 + {
1.864 + return internal_visit( operand.get(), 1L );
1.865 + }
1.866 +
1.867 + template <typename T>
1.868 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.869 + internal_visit(const boost::recursive_wrapper<T>& operand, long)
1.870 + {
1.871 + return internal_visit( operand.get(), 1L );
1.872 + }
1.873 +
1.874 + template <typename T>
1.875 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.876 + internal_visit(boost::detail::reference_content<T>& operand, long)
1.877 + {
1.878 + return internal_visit( operand.get(), 1L );
1.879 + }
1.880 +
1.881 + template <typename T>
1.882 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.883 + internal_visit(const boost::detail::reference_content<T>& operand, long)
1.884 + {
1.885 + return internal_visit( operand.get(), 1L );
1.886 + }
1.887 +
1.888 + template <typename T>
1.889 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.890 + internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1.891 + {
1.892 + return internal_visit( operand.get(), 1L );
1.893 + }
1.894 +
1.895 + template <typename T>
1.896 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1.897 + internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1.898 + {
1.899 + return internal_visit( operand.get(), 1L );
1.900 + }
1.901 +
1.902 +};
1.903 +
1.904 +}} // namespace detail::variant
1.905 +
1.906 +///////////////////////////////////////////////////////////////////////////////
1.907 +// class template variant (concept inspired by Andrei Alexandrescu)
1.908 +//
1.909 +// See docs and boost/variant/variant_fwd.hpp for more information.
1.910 +//
1.911 +template <
1.912 + typename T0_
1.913 + , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1.914 + >
1.915 +class variant
1.916 +{
1.917 +private: // helpers, for typedefs (below)
1.918 +
1.919 + typedef variant wknd_self_t;
1.920 +
1.921 + struct is_recursive_
1.922 + : detail::variant::is_recursive_flag<T0_>
1.923 + {
1.924 + };
1.925 +
1.926 + typedef typename mpl::eval_if<
1.927 + is_recursive_
1.928 + , T0_
1.929 + , mpl::identity< T0_ >
1.930 + >::type unwrapped_T0_;
1.931 +
1.932 + struct is_sequence_based_
1.933 + : detail::variant::is_over_sequence<unwrapped_T0_>
1.934 + {
1.935 + };
1.936 +
1.937 +#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1.938 +
1.939 +private: // helpers, for typedefs (below)
1.940 +
1.941 + typedef typename mpl::eval_if<
1.942 + is_sequence_based_
1.943 + , unwrapped_T0_ // over_sequence<...>::type
1.944 + , detail::variant::make_variant_list<
1.945 + unwrapped_T0_
1.946 + , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1.947 + >
1.948 + >::type specified_types;
1.949 +
1.950 + BOOST_STATIC_ASSERT((
1.951 + ::boost::mpl::not_< mpl::empty<specified_types> >::value
1.952 + ));
1.953 +
1.954 + typedef typename mpl::eval_if<
1.955 + is_recursive_
1.956 + , mpl::transform<
1.957 + specified_types
1.958 + , mpl::protect<
1.959 + detail::variant::quoted_enable_recursive<wknd_self_t>
1.960 + >
1.961 + >
1.962 + , mpl::identity< specified_types >
1.963 + >::type recursive_enabled_types;
1.964 +
1.965 +public: // public typedefs
1.966 +
1.967 + typedef typename mpl::transform<
1.968 + recursive_enabled_types
1.969 + , unwrap_recursive<mpl::_1>
1.970 + >::type types;
1.971 +
1.972 +private: // internal typedefs
1.973 +
1.974 + typedef typename mpl::transform<
1.975 + recursive_enabled_types
1.976 + , mpl::protect< detail::make_reference_content<> >
1.977 + >::type internal_types;
1.978 +
1.979 + typedef typename mpl::front<
1.980 + internal_types
1.981 + >::type internal_T0;
1.982 +
1.983 +#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1.984 +
1.985 +private: // helpers, for typedefs (below)
1.986 +
1.987 + typedef unwrapped_T0_ T0;
1.988 +
1.989 + #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1.990 + typedef typename mpl::eval_if< \
1.991 + is_recursive_ \
1.992 + , detail::variant::enable_recursive< \
1.993 + BOOST_PP_CAT(T,N) \
1.994 + , wknd_self_t \
1.995 + > \
1.996 + , mpl::identity< BOOST_PP_CAT(T,N) > \
1.997 + >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1.998 + /**/
1.999 +
1.1000 + BOOST_PP_REPEAT(
1.1001 + BOOST_VARIANT_LIMIT_TYPES
1.1002 + , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1.1003 + , _
1.1004 + )
1.1005 +
1.1006 + #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1.1007 +
1.1008 + #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1.1009 + typedef typename unwrap_recursive< \
1.1010 + BOOST_PP_CAT(recursive_enabled_T,N) \
1.1011 + >::type BOOST_PP_CAT(public_T,N); \
1.1012 + /**/
1.1013 +
1.1014 + BOOST_PP_REPEAT(
1.1015 + BOOST_VARIANT_LIMIT_TYPES
1.1016 + , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1.1017 + , _
1.1018 + )
1.1019 +
1.1020 + #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1.1021 +
1.1022 +public: // public typedefs
1.1023 +
1.1024 + typedef typename detail::variant::make_variant_list<
1.1025 + BOOST_VARIANT_ENUM_PARAMS(public_T)
1.1026 + >::type types;
1.1027 +
1.1028 +private: // helpers, for internal typedefs (below)
1.1029 +
1.1030 + #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1.1031 + typedef detail::make_reference_content< \
1.1032 + BOOST_PP_CAT(recursive_enabled_T,N) \
1.1033 + >::type BOOST_PP_CAT(internal_T,N); \
1.1034 + /**/
1.1035 +
1.1036 + BOOST_PP_REPEAT(
1.1037 + BOOST_VARIANT_LIMIT_TYPES
1.1038 + , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1.1039 + , _
1.1040 + )
1.1041 +
1.1042 + #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1.1043 +
1.1044 +private: // internal typedefs
1.1045 +
1.1046 + typedef typename detail::variant::make_variant_list<
1.1047 + BOOST_VARIANT_ENUM_PARAMS(internal_T)
1.1048 + >::type internal_types;
1.1049 +
1.1050 +private: // static precondition assertions
1.1051 +
1.1052 + // NOTE TO USER :
1.1053 + // variant< type-sequence > syntax is not supported on this compiler!
1.1054 + //
1.1055 + BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1.1056 +
1.1057 +#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1.1058 +
1.1059 +private: // helpers, for representation (below)
1.1060 +
1.1061 + typedef typename detail::variant::find_fallback_type<
1.1062 + internal_types
1.1063 + >::type fallback_type_result_;
1.1064 +
1.1065 + typedef typename fallback_type_result_::first
1.1066 + fallback_type_index_;
1.1067 + typedef typename fallback_type_result_::second
1.1068 + fallback_type_;
1.1069 +
1.1070 + struct has_fallback_type_
1.1071 + : mpl::not_<
1.1072 + is_same< fallback_type_, detail::variant::no_fallback_type >
1.1073 + >
1.1074 + {
1.1075 + };
1.1076 +
1.1077 + typedef has_fallback_type_
1.1078 + never_uses_backup_flag;
1.1079 +
1.1080 + typedef typename detail::variant::make_storage<
1.1081 + internal_types, never_uses_backup_flag
1.1082 + >::type storage_t;
1.1083 +
1.1084 +private: // helpers, for representation (below)
1.1085 +
1.1086 + // which_ on:
1.1087 + // * [0, size<internal_types>) indicates stack content
1.1088 + // * [-size<internal_types>, 0) indicates pointer to heap backup
1.1089 + // if which_ >= 0:
1.1090 + // * then which() -> which_
1.1091 + // * else which() -> -(which_ + 1)
1.1092 +
1.1093 +#if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1.1094 +
1.1095 + typedef int which_t;
1.1096 +
1.1097 +#else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1.1098 +
1.1099 + // [if O1_size available, then attempt which_t size optimization...]
1.1100 + // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1.1101 + typedef typename mpl::eval_if<
1.1102 + mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1.1103 + , mpl::identity< int >
1.1104 + , mpl::if_<
1.1105 + mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1.1106 + , signed char
1.1107 + , int
1.1108 + >
1.1109 + >::type which_t;
1.1110 +
1.1111 +#endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1.1112 +
1.1113 +// representation -- private when possible
1.1114 +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1.1115 + private:
1.1116 +#else
1.1117 + public:
1.1118 +#endif
1.1119 +
1.1120 + which_t which_;
1.1121 + storage_t storage_;
1.1122 +
1.1123 + void indicate_which(int which)
1.1124 + {
1.1125 + which_ = static_cast<which_t>( which );
1.1126 + }
1.1127 +
1.1128 + void indicate_backup_which(int which)
1.1129 + {
1.1130 + which_ = static_cast<which_t>( -(which + 1) );
1.1131 + }
1.1132 +
1.1133 +private: // helpers, for queries (below)
1.1134 +
1.1135 + bool using_backup() const
1.1136 + {
1.1137 + return which_ < 0;
1.1138 + }
1.1139 +
1.1140 +public: // queries
1.1141 +
1.1142 + int which() const
1.1143 + {
1.1144 + // If using heap backup...
1.1145 + if (using_backup())
1.1146 + // ...then return adjusted which_:
1.1147 + return -(which_ + 1);
1.1148 +
1.1149 + // Otherwise, return which_ directly:
1.1150 + return which_;
1.1151 + }
1.1152 +
1.1153 +private: // helpers, for structors (below)
1.1154 +
1.1155 + struct initializer
1.1156 + : BOOST_VARIANT_AUX_INITIALIZER_T(
1.1157 + recursive_enabled_types, recursive_enabled_T
1.1158 + )
1.1159 + {
1.1160 + };
1.1161 +
1.1162 + void destroy_content()
1.1163 + {
1.1164 + detail::variant::destroyer visitor;
1.1165 + this->internal_apply_visitor(visitor);
1.1166 + }
1.1167 +
1.1168 +public: // structors
1.1169 +
1.1170 + ~variant()
1.1171 + {
1.1172 + destroy_content();
1.1173 + }
1.1174 +
1.1175 + variant()
1.1176 + {
1.1177 + // NOTE TO USER :
1.1178 + // Compile error from here indicates that the first bound
1.1179 + // type is not default-constructible, and so variant cannot
1.1180 + // support its own default-construction.
1.1181 + //
1.1182 + new( storage_.address() ) internal_T0();
1.1183 + indicate_which(0); // zero is the index of the first bounded type
1.1184 + }
1.1185 +
1.1186 +private: // helpers, for structors, cont. (below)
1.1187 +
1.1188 + class convert_copy_into
1.1189 + : public static_visitor<int>
1.1190 + {
1.1191 + private: // representation
1.1192 +
1.1193 + void* storage_;
1.1194 +
1.1195 + public: // structors
1.1196 +
1.1197 + explicit convert_copy_into(void* storage)
1.1198 + : storage_(storage)
1.1199 + {
1.1200 + }
1.1201 +
1.1202 + public: // internal visitor interfaces (below)
1.1203 +
1.1204 + template <typename T>
1.1205 + int internal_visit(T& operand, int) const
1.1206 + {
1.1207 + // NOTE TO USER :
1.1208 + // Compile error here indicates one of the source variant's types
1.1209 + // cannot be unambiguously converted to the destination variant's
1.1210 + // types (or that no conversion exists).
1.1211 + //
1.1212 + return initializer::initialize(storage_, operand);
1.1213 + }
1.1214 +
1.1215 +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1.1216 + template <typename T>
1.1217 + result_type internal_visit(const T& operand, int) const
1.1218 + {
1.1219 + return initializer::initialize(storage_, operand);
1.1220 + }
1.1221 +# endif
1.1222 +
1.1223 + template <typename T>
1.1224 + int internal_visit(boost::detail::reference_content<T>& operand, long) const
1.1225 + {
1.1226 + return internal_visit( operand.get(), 1L );
1.1227 + }
1.1228 +
1.1229 + template <typename T>
1.1230 + int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1.1231 + {
1.1232 + return internal_visit( operand.get(), 1L );
1.1233 + }
1.1234 +
1.1235 + template <typename T>
1.1236 + int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1.1237 + {
1.1238 + return internal_visit( operand.get(), 1L );
1.1239 + }
1.1240 +
1.1241 + template <typename T>
1.1242 + int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1.1243 + {
1.1244 + return internal_visit( operand.get(), 1L );
1.1245 + }
1.1246 +
1.1247 + template <typename T>
1.1248 + int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1.1249 + {
1.1250 + return internal_visit( operand.get(), 1L );
1.1251 + }
1.1252 +
1.1253 + template <typename T>
1.1254 + int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1.1255 + {
1.1256 + return internal_visit( operand.get(), 1L );
1.1257 + }
1.1258 +
1.1259 + };
1.1260 +
1.1261 + friend class convert_copy_into;
1.1262 +
1.1263 +private: // helpers, for structors, below
1.1264 +
1.1265 + template <typename T>
1.1266 + void convert_construct(
1.1267 + T& operand
1.1268 + , int
1.1269 + , mpl::false_ = mpl::false_() // is_foreign_variant
1.1270 + )
1.1271 + {
1.1272 + // NOTE TO USER :
1.1273 + // Compile error here indicates that the given type is not
1.1274 + // unambiguously convertible to one of the variant's types
1.1275 + // (or that no conversion exists).
1.1276 + //
1.1277 + indicate_which(
1.1278 + initializer::initialize(
1.1279 + storage_.address()
1.1280 + , operand
1.1281 + )
1.1282 + );
1.1283 + }
1.1284 +
1.1285 + template <typename Variant>
1.1286 + void convert_construct(
1.1287 + Variant& operand
1.1288 + , long
1.1289 + , mpl::true_// is_foreign_variant
1.1290 + )
1.1291 + {
1.1292 + convert_copy_into visitor(storage_.address());
1.1293 + indicate_which(
1.1294 + operand.internal_apply_visitor(visitor)
1.1295 + );
1.1296 + }
1.1297 +
1.1298 + template <typename Variant>
1.1299 + void convert_construct_variant(Variant& operand)
1.1300 + {
1.1301 + // [Determine if the given variant is itself a bounded type, or if its
1.1302 + // content needs to be converted (i.e., it is a 'foreign' variant):]
1.1303 + //
1.1304 +
1.1305 + typedef typename mpl::find_if<
1.1306 + types
1.1307 + , is_same<
1.1308 + add_const<mpl::_1>
1.1309 + , const Variant
1.1310 + >
1.1311 + >::type found_it;
1.1312 +
1.1313 + typedef typename mpl::end<types>::type not_found;
1.1314 + typedef typename is_same<
1.1315 + found_it, not_found
1.1316 + >::type is_foreign_variant;
1.1317 +
1.1318 + // Convert construct from operand:
1.1319 + convert_construct(
1.1320 + operand, 1L
1.1321 + , is_foreign_variant()
1.1322 + );
1.1323 + }
1.1324 +
1.1325 + template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1.1326 + void convert_construct(
1.1327 + boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1.1328 + , long
1.1329 + )
1.1330 + {
1.1331 + convert_construct_variant(operand);
1.1332 + }
1.1333 +
1.1334 + template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1.1335 + void convert_construct(
1.1336 + const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1.1337 + , long
1.1338 + )
1.1339 + {
1.1340 + convert_construct_variant(operand);
1.1341 + }
1.1342 +
1.1343 +public: // structors, cont.
1.1344 +
1.1345 +#if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
1.1346 +
1.1347 + template <typename T>
1.1348 + variant(const T& operand)
1.1349 + {
1.1350 + convert_construct(operand, 1L);
1.1351 + }
1.1352 +
1.1353 + template <typename T>
1.1354 + variant(T& operand)
1.1355 + {
1.1356 + convert_construct(operand, 1L);
1.1357 + }
1.1358 +
1.1359 +#elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1.1360 +
1.1361 + // For compilers that cannot distinguish between T& and const T& in
1.1362 + // template constructors, but do fully support SFINAE, we can workaround:
1.1363 +
1.1364 + template <typename T>
1.1365 + variant(const T& operand)
1.1366 + {
1.1367 + convert_construct(operand, 1L);
1.1368 + }
1.1369 +
1.1370 + template <typename T>
1.1371 + variant(
1.1372 + T& operand
1.1373 + , typename enable_if<
1.1374 + mpl::not_< is_const<T> >
1.1375 + , void
1.1376 + >::type* = 0
1.1377 + )
1.1378 + {
1.1379 + convert_construct(operand, 1L);
1.1380 + }
1.1381 +
1.1382 +#else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1.1383 +
1.1384 + // For compilers that cannot distinguish between T& and const T& in
1.1385 + // template constructors, and do NOT support SFINAE, we can't workaround:
1.1386 +
1.1387 + template <typename T>
1.1388 + variant(const T& operand)
1.1389 + {
1.1390 + convert_construct(operand, 1L);
1.1391 + }
1.1392 +
1.1393 +#endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
1.1394 +
1.1395 +public: // structors, cont.
1.1396 +
1.1397 + // [MSVC6 requires copy constructor appear after template constructors]
1.1398 + variant(const variant& operand)
1.1399 + {
1.1400 + // Copy the value of operand into *this...
1.1401 + detail::variant::copy_into visitor( storage_.address() );
1.1402 + operand.internal_apply_visitor(visitor);
1.1403 +
1.1404 + // ...and activate the *this's primary storage on success:
1.1405 + indicate_which(operand.which());
1.1406 + }
1.1407 +
1.1408 +private: // helpers, for modifiers (below)
1.1409 +
1.1410 +# if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1.1411 + template <typename Variant, typename RhsT>
1.1412 + friend class detail::variant::backup_assigner;
1.1413 +# endif
1.1414 +
1.1415 + // class assigner
1.1416 + //
1.1417 + // Internal visitor that "assigns" the visited value to the given variant
1.1418 + // by appropriate destruction and copy-construction.
1.1419 + //
1.1420 +
1.1421 + class assigner
1.1422 + : public static_visitor<>
1.1423 + {
1.1424 + private: // representation
1.1425 +
1.1426 + variant& lhs_;
1.1427 + int rhs_which_;
1.1428 +
1.1429 + public: // structors
1.1430 +
1.1431 + assigner(variant& lhs, int rhs_which)
1.1432 + : lhs_(lhs)
1.1433 + , rhs_which_(rhs_which)
1.1434 + {
1.1435 + }
1.1436 +
1.1437 + private: // helpers, for internal visitor interface (below)
1.1438 +
1.1439 + template <typename RhsT, typename B1, typename B2>
1.1440 + void assign_impl(
1.1441 + const RhsT& rhs_content
1.1442 + , mpl::true_// has_nothrow_copy
1.1443 + , B1// has_nothrow_move_constructor
1.1444 + , B2// has_fallback_type
1.1445 + )
1.1446 + {
1.1447 + // Destroy lhs's content...
1.1448 + lhs_.destroy_content(); // nothrow
1.1449 +
1.1450 + // ...copy rhs content into lhs's storage...
1.1451 + new(lhs_.storage_.address())
1.1452 + RhsT( rhs_content ); // nothrow
1.1453 +
1.1454 + // ...and indicate new content type:
1.1455 + lhs_.indicate_which(rhs_which_); // nothrow
1.1456 + }
1.1457 +
1.1458 + template <typename RhsT, typename B>
1.1459 + void assign_impl(
1.1460 + const RhsT& rhs_content
1.1461 + , mpl::false_// has_nothrow_copy
1.1462 + , mpl::true_// has_nothrow_move_constructor
1.1463 + , B// has_fallback_type
1.1464 + )
1.1465 + {
1.1466 + // Attempt to make a temporary copy (so as to move it below)...
1.1467 + RhsT temp(rhs_content);
1.1468 +
1.1469 + // ...and upon success destroy lhs's content...
1.1470 + lhs_.destroy_content(); // nothrow
1.1471 +
1.1472 + // ...move the temporary copy into lhs's storage...
1.1473 + new(lhs_.storage_.address())
1.1474 + RhsT( detail::variant::move(temp) ); // nothrow
1.1475 +
1.1476 + // ...and indicate new content type:
1.1477 + lhs_.indicate_which(rhs_which_); // nothrow
1.1478 + }
1.1479 +
1.1480 + template <typename RhsT>
1.1481 + void assign_impl(
1.1482 + const RhsT& rhs_content
1.1483 + , mpl::false_// has_nothrow_copy
1.1484 + , mpl::false_// has_nothrow_move_constructor
1.1485 + , mpl::true_// has_fallback_type
1.1486 + )
1.1487 + {
1.1488 + // Destroy lhs's content...
1.1489 + lhs_.destroy_content(); // nothrow
1.1490 +
1.1491 + try
1.1492 + {
1.1493 + // ...and attempt to copy rhs's content into lhs's storage:
1.1494 + new(lhs_.storage_.address())
1.1495 + RhsT( rhs_content );
1.1496 + }
1.1497 + catch (...)
1.1498 + {
1.1499 + // In case of failure, default-construct fallback type in lhs's storage...
1.1500 + new (lhs_.storage_.address())
1.1501 + fallback_type_; // nothrow
1.1502 +
1.1503 + // ...indicate construction of fallback type...
1.1504 + lhs_.indicate_which(
1.1505 + BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1.1506 + ); // nothrow
1.1507 +
1.1508 + // ...and rethrow:
1.1509 + throw;
1.1510 + }
1.1511 +
1.1512 + // In the event of success, indicate new content type:
1.1513 + lhs_.indicate_which(rhs_which_); // nothrow
1.1514 + }
1.1515 +
1.1516 + template <typename RhsT>
1.1517 + void assign_impl(
1.1518 + const RhsT& rhs_content
1.1519 + , mpl::false_// has_nothrow_copy
1.1520 + , mpl::false_// has_nothrow_move_constructor
1.1521 + , mpl::false_// has_fallback_type
1.1522 + )
1.1523 + {
1.1524 + detail::variant::backup_assigner<wknd_self_t, RhsT>
1.1525 + visitor(lhs_, rhs_which_, rhs_content);
1.1526 + lhs_.internal_apply_visitor(visitor);
1.1527 + }
1.1528 +
1.1529 + public: // internal visitor interfaces
1.1530 +
1.1531 + template <typename RhsT>
1.1532 + BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1.1533 + internal_visit(const RhsT& rhs_content, int)
1.1534 + {
1.1535 + typedef typename has_nothrow_copy<RhsT>::type
1.1536 + nothrow_copy;
1.1537 + typedef typename mpl::or_< // reduces compile-time
1.1538 + nothrow_copy
1.1539 + , detail::variant::has_nothrow_move_constructor<RhsT>
1.1540 + >::type nothrow_move_constructor;
1.1541 +
1.1542 + assign_impl(
1.1543 + rhs_content
1.1544 + , nothrow_copy()
1.1545 + , nothrow_move_constructor()
1.1546 + , has_fallback_type_()
1.1547 + );
1.1548 +
1.1549 + BOOST_VARIANT_AUX_RETURN_VOID;
1.1550 + }
1.1551 +
1.1552 + };
1.1553 +
1.1554 + friend class assigner;
1.1555 +
1.1556 + void variant_assign(const variant& rhs)
1.1557 + {
1.1558 + // If the contained types are EXACTLY the same...
1.1559 + if (which_ == rhs.which_)
1.1560 + {
1.1561 + // ...then assign rhs's storage to lhs's content:
1.1562 + detail::variant::assign_storage visitor(rhs.storage_.address());
1.1563 + this->internal_apply_visitor(visitor);
1.1564 + }
1.1565 + else
1.1566 + {
1.1567 + // Otherwise, perform general (copy-based) variant assignment:
1.1568 + assigner visitor(*this, rhs.which());
1.1569 + rhs.internal_apply_visitor(visitor);
1.1570 + }
1.1571 + }
1.1572 +
1.1573 +private: // helpers, for modifiers (below)
1.1574 +
1.1575 + template <typename T>
1.1576 + void assign(const T& rhs)
1.1577 + {
1.1578 + // If direct T-to-T assignment is not possible...
1.1579 + detail::variant::direct_assigner<const T> direct_assign(rhs);
1.1580 + if (this->apply_visitor(direct_assign) == false)
1.1581 + {
1.1582 + // ...then convert rhs to variant and assign:
1.1583 + //
1.1584 + // While potentially inefficient, the following construction of a
1.1585 + // variant allows T as any type convertible to one of the bounded
1.1586 + // types without excessive code redundancy.
1.1587 + //
1.1588 + variant temp(rhs);
1.1589 + variant_assign( detail::variant::move(temp) );
1.1590 + }
1.1591 + }
1.1592 +
1.1593 +public: // modifiers
1.1594 +
1.1595 + template <typename T>
1.1596 + variant& operator=(const T& rhs)
1.1597 + {
1.1598 + assign(rhs);
1.1599 + return *this;
1.1600 + }
1.1601 +
1.1602 + // [MSVC6 requires copy assign appear after templated operator=]
1.1603 + variant& operator=(const variant& rhs)
1.1604 + {
1.1605 + variant_assign(rhs);
1.1606 + return *this;
1.1607 + }
1.1608 +
1.1609 + void swap(variant& rhs)
1.1610 + {
1.1611 + // If the contained types are the same...
1.1612 + if (which() == rhs.which())
1.1613 + {
1.1614 + // ...then swap the values directly:
1.1615 + detail::variant::swap_with<variant> visitor(rhs);
1.1616 + this->apply_visitor(visitor);
1.1617 + }
1.1618 + else
1.1619 + {
1.1620 + // ...otherwise, perform general variant swap:
1.1621 + variant tmp( detail::variant::move(rhs) );
1.1622 + rhs = detail::variant::move(*this);
1.1623 + *this = detail::variant::move(tmp);
1.1624 + }
1.1625 + }
1.1626 +
1.1627 +public: // queries
1.1628 +
1.1629 + //
1.1630 + // NOTE: member which() defined above.
1.1631 + //
1.1632 +
1.1633 + bool empty() const
1.1634 + {
1.1635 + return false;
1.1636 + }
1.1637 +
1.1638 + const std::type_info& type() const
1.1639 + {
1.1640 + detail::variant::reflect visitor;
1.1641 + return this->apply_visitor(visitor);
1.1642 + }
1.1643 +
1.1644 +public: // prevent comparison with foreign types
1.1645 +
1.1646 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1.1647 +
1.1648 +# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1.1649 + void
1.1650 +
1.1651 +#else // MSVC7
1.1652 +
1.1653 + //
1.1654 + // MSVC7 gives error about return types for above being different than
1.1655 + // the true comparison operator overloads:
1.1656 + //
1.1657 +
1.1658 +# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1.1659 + bool
1.1660 +
1.1661 +#endif // MSVC7 workaround
1.1662 +
1.1663 + template <typename U>
1.1664 + BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1.1665 + operator==(const U&) const
1.1666 + {
1.1667 + BOOST_STATIC_ASSERT( false && sizeof(U) );
1.1668 + }
1.1669 +
1.1670 + template <typename U>
1.1671 + BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1.1672 + operator<(const U&) const
1.1673 + {
1.1674 + BOOST_STATIC_ASSERT( false && sizeof(U) );
1.1675 + }
1.1676 +
1.1677 +public: // comparison operators
1.1678 +
1.1679 + // [MSVC6 requires these operators appear after template operators]
1.1680 +
1.1681 + bool operator==(const variant& rhs) const
1.1682 + {
1.1683 + if (this->which() != rhs.which())
1.1684 + return false;
1.1685 +
1.1686 + detail::variant::comparer<
1.1687 + variant, detail::variant::equal_comp
1.1688 + > visitor(*this);
1.1689 + return rhs.apply_visitor(visitor);
1.1690 + }
1.1691 +
1.1692 + bool operator<(const variant& rhs) const
1.1693 + {
1.1694 + //
1.1695 + // Dirk Schreib suggested this collating order.
1.1696 + //
1.1697 +
1.1698 + if (this->which() != rhs.which())
1.1699 + return this->which() < rhs.which();
1.1700 +
1.1701 + detail::variant::comparer<
1.1702 + variant, detail::variant::less_comp
1.1703 + > visitor(*this);
1.1704 + return rhs.apply_visitor(visitor);
1.1705 + }
1.1706 +
1.1707 +// helpers, for visitation support (below) -- private when possible
1.1708 +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1.1709 +
1.1710 + template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
1.1711 + friend class variant;
1.1712 +
1.1713 +private:
1.1714 +
1.1715 +#else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1.1716 +
1.1717 +public:
1.1718 +
1.1719 +#endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1.1720 +
1.1721 + template <typename Visitor, typename VoidPtrCV>
1.1722 + static
1.1723 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1.1724 + typename Visitor::result_type
1.1725 + )
1.1726 + internal_apply_visitor_impl(
1.1727 + int internal_which
1.1728 + , int logical_which
1.1729 + , Visitor& visitor
1.1730 + , VoidPtrCV storage
1.1731 + )
1.1732 + {
1.1733 + typedef mpl::int_<0> first_which;
1.1734 + typedef typename mpl::begin<internal_types>::type first_it;
1.1735 + typedef typename mpl::end<internal_types>::type last_it;
1.1736 +
1.1737 + typedef detail::variant::visitation_impl_step<
1.1738 + first_it, last_it
1.1739 + > first_step;
1.1740 +
1.1741 + return detail::variant::visitation_impl(
1.1742 + internal_which, logical_which
1.1743 + , visitor, storage, mpl::false_()
1.1744 + , never_uses_backup_flag()
1.1745 + , static_cast<first_which*>(0), static_cast<first_step*>(0)
1.1746 + );
1.1747 + }
1.1748 +
1.1749 + template <typename Visitor>
1.1750 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1.1751 + typename Visitor::result_type
1.1752 + )
1.1753 + internal_apply_visitor(Visitor& visitor)
1.1754 + {
1.1755 + return internal_apply_visitor_impl(
1.1756 + which_, which(), visitor, storage_.address()
1.1757 + );
1.1758 + }
1.1759 +
1.1760 + template <typename Visitor>
1.1761 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1.1762 + typename Visitor::result_type
1.1763 + )
1.1764 + internal_apply_visitor(Visitor& visitor) const
1.1765 + {
1.1766 + return internal_apply_visitor_impl(
1.1767 + which_, which(), visitor, storage_.address()
1.1768 + );
1.1769 + }
1.1770 +
1.1771 +public: // visitation support
1.1772 +
1.1773 + template <typename Visitor>
1.1774 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1.1775 + typename Visitor::result_type
1.1776 + )
1.1777 + apply_visitor(Visitor& visitor)
1.1778 + {
1.1779 + detail::variant::invoke_visitor<Visitor> invoker(visitor);
1.1780 + return this->internal_apply_visitor(invoker);
1.1781 + }
1.1782 +
1.1783 + template <typename Visitor>
1.1784 + BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1.1785 + typename Visitor::result_type
1.1786 + )
1.1787 + apply_visitor(Visitor& visitor) const
1.1788 + {
1.1789 + detail::variant::invoke_visitor<Visitor> invoker(visitor);
1.1790 + return this->internal_apply_visitor(invoker);
1.1791 + }
1.1792 +
1.1793 +}; // class variant
1.1794 +
1.1795 +///////////////////////////////////////////////////////////////////////////////
1.1796 +// metafunction make_variant_over
1.1797 +//
1.1798 +// See docs and boost/variant/variant_fwd.hpp for more information.
1.1799 +//
1.1800 +template <typename Types>
1.1801 +struct make_variant_over
1.1802 +{
1.1803 +private: // precondition assertions
1.1804 +
1.1805 +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1.1806 + BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
1.1807 +#endif
1.1808 +
1.1809 +public: // metafunction result
1.1810 +
1.1811 + typedef variant<
1.1812 + detail::variant::over_sequence< Types >
1.1813 + > type;
1.1814 +
1.1815 +};
1.1816 +
1.1817 +///////////////////////////////////////////////////////////////////////////////
1.1818 +// function template swap
1.1819 +//
1.1820 +// Swaps two variants of the same type (i.e., identical specification).
1.1821 +//
1.1822 +template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
1.1823 +inline void swap(
1.1824 + variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
1.1825 + , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
1.1826 + )
1.1827 +{
1.1828 + lhs.swap(rhs);
1.1829 +}
1.1830 +
1.1831 +} // namespace boost
1.1832 +
1.1833 +// implementation additions
1.1834 +#include "boost/variant/detail/variant_io.hpp"
1.1835 +
1.1836 +#endif // BOOST_VARIANT_VARIANT_HPP