PageRenderTime 225ms CodeModel.GetById 68ms app.highlight 132ms RepoModel.GetById 2ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/variant/variant.hpp

http://hadesmem.googlecode.com/
C++ Header | 1895 lines | 1269 code | 369 blank | 257 comment | 18 complexity | 1c0d85abe939f4e5b3a66e48e72aea49 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1//-----------------------------------------------------------------------------
   2// boost variant/variant.hpp header file
   3// See http://www.boost.org for updates, documentation, and revision history.
   4//-----------------------------------------------------------------------------
   5//
   6// Copyright (c) 2002-2003
   7// Eric Friedman, Itay Maman
   8//
   9// Distributed under the Boost Software License, Version 1.0. (See
  10// accompanying file LICENSE_1_0.txt or copy at
  11// http://www.boost.org/LICENSE_1_0.txt)
  12
  13#ifndef BOOST_VARIANT_VARIANT_HPP
  14#define BOOST_VARIANT_VARIANT_HPP
  15
  16#include <cstddef> // for std::size_t
  17#include <new> // for placement new
  18
  19#if !defined(BOOST_NO_TYPEID)
  20#include <typeinfo> // for typeid, std::type_info
  21#endif // BOOST_NO_TYPEID
  22
  23#include "boost/variant/detail/config.hpp"
  24#include "boost/mpl/aux_/config/eti.hpp"
  25#include "boost/mpl/aux_/value_wknd.hpp"
  26
  27#include "boost/variant/variant_fwd.hpp"
  28#include "boost/variant/detail/backup_holder.hpp"
  29#include "boost/variant/detail/enable_recursive_fwd.hpp"
  30#include "boost/variant/detail/forced_return.hpp"
  31#include "boost/variant/detail/initializer.hpp"
  32#include "boost/variant/detail/make_variant_list.hpp"
  33#include "boost/variant/detail/over_sequence.hpp"
  34#include "boost/variant/detail/visitation_impl.hpp"
  35
  36#include "boost/variant/detail/generic_result_type.hpp"
  37#include "boost/variant/detail/has_nothrow_move.hpp"
  38#include "boost/variant/detail/move.hpp"
  39
  40#include "boost/detail/reference_content.hpp"
  41#include "boost/aligned_storage.hpp"
  42#include "boost/blank.hpp"
  43#include "boost/math/common_factor_ct.hpp"
  44#include "boost/static_assert.hpp"
  45#include "boost/preprocessor/cat.hpp"
  46#include "boost/preprocessor/repeat.hpp"
  47#include "boost/type_traits/alignment_of.hpp"
  48#include "boost/type_traits/add_const.hpp"
  49#include "boost/type_traits/has_nothrow_constructor.hpp"
  50#include "boost/type_traits/has_nothrow_copy.hpp"
  51#include "boost/type_traits/is_const.hpp"
  52#include "boost/type_traits/is_same.hpp"
  53#include "boost/utility/enable_if.hpp"
  54#include "boost/variant/recursive_wrapper_fwd.hpp"
  55#include "boost/variant/static_visitor.hpp"
  56
  57#include "boost/mpl/assert.hpp"
  58#include "boost/mpl/begin_end.hpp"
  59#include "boost/mpl/bool.hpp"
  60#include "boost/mpl/deref.hpp"
  61#include "boost/mpl/empty.hpp"
  62#include "boost/mpl/eval_if.hpp"
  63#include "boost/mpl/find_if.hpp"
  64#include "boost/mpl/fold.hpp"
  65#include "boost/mpl/front.hpp"
  66#include "boost/mpl/identity.hpp"
  67#include "boost/mpl/if.hpp"
  68#include "boost/mpl/int.hpp"
  69#include "boost/mpl/is_sequence.hpp"
  70#include "boost/mpl/iterator_range.hpp"
  71#include "boost/mpl/iter_fold_if.hpp"
  72#include "boost/mpl/logical.hpp"
  73#include "boost/mpl/max_element.hpp"
  74#include "boost/mpl/next.hpp"
  75#include "boost/mpl/not.hpp"
  76#include "boost/mpl/pair.hpp"
  77#include "boost/mpl/protect.hpp"
  78#include "boost/mpl/push_front.hpp"
  79#include "boost/mpl/same_as.hpp"
  80#include "boost/mpl/size_t.hpp"
  81#include "boost/mpl/sizeof.hpp"
  82#include "boost/mpl/transform.hpp"
  83
  84///////////////////////////////////////////////////////////////////////////////
  85// Implementation Macros:
  86//
  87// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
  88//   Defined in boost/variant/detail/visitation_impl.hpp.
  89//
  90// BOOST_VARIANT_MINIMIZE_SIZE
  91//   When #defined, implementation employs all known means to minimize the
  92//   size of variant obje   cts. However, often unsuccessful due to alignment
  93//   issues, and potentially harmful to runtime speed, so not enabled by
  94//   default. (TODO: Investigate further.)
  95
  96#if defined(BOOST_VARIANT_MINIMIZE_SIZE)
  97#   include <climits> // for SCHAR_MAX
  98#   include "boost/mpl/eval_if.hpp"
  99#   include "boost/mpl/equal_to.hpp"
 100#   include "boost/mpl/identity.hpp"
 101#   include "boost/mpl/int.hpp"
 102#   include "boost/mpl/if.hpp"
 103#   include "boost/mpl/less.hpp"
 104#   include "boost/mpl/long.hpp"
 105#   include "boost/mpl/O1_size.hpp"
 106#endif
 107
 108
 109namespace boost {
 110
 111namespace detail { namespace variant {
 112
 113///////////////////////////////////////////////////////////////////////////////
 114// (detail) metafunction max_value
 115//
 116// Finds the maximum value of the unary metafunction F over Sequence.
 117//
 118template <typename Sequence, typename F>
 119struct max_value
 120{
 121private: // helpers, for metafunction result (below)
 122
 123    typedef typename mpl::transform1<Sequence, F>::type transformed_;
 124    typedef typename mpl::max_element<transformed_
 125          
 126        >::type max_it;
 127
 128public: // metafunction result
 129
 130    typedef typename mpl::deref<max_it>::type
 131        type;
 132
 133};
 134
 135struct add_alignment
 136{
 137    template <typename State, typename Item>
 138    struct apply
 139        : mpl::size_t<
 140              ::boost::math::static_lcm<
 141                  BOOST_MPL_AUX_VALUE_WKND(State)::value
 142                , ::boost::alignment_of<Item>::value
 143                >::value
 144            >
 145    {};
 146};
 147
 148///////////////////////////////////////////////////////////////////////////////
 149// (detail) metafunction find_fallback_type
 150//
 151// Provides a fallback (i.e., nothrow default-constructible) type from the
 152// specified sequence, or no_fallback_type if not found.
 153//
 154// This implementation is designed to prefer boost::blank over other potential
 155// fallback types, regardless of its position in the specified sequence.
 156//
 157
 158class no_fallback_type;
 159
 160struct find_fallback_type_pred
 161{
 162    template <typename Iterator>
 163    struct apply
 164    {
 165    private:
 166        typedef typename mpl::deref<Iterator>::type t_;
 167
 168    public:
 169        typedef mpl::not_< has_nothrow_constructor<t_> > type;
 170    };
 171};
 172
 173template <typename Types>
 174struct find_fallback_type
 175{
 176private: // helpers, for metafunction result (below)
 177
 178    typedef typename mpl::end<Types>::type end_it;
 179
 180    // [Find the first suitable fallback type...]
 181
 182    typedef typename mpl::iter_fold_if<
 183          Types
 184        , mpl::int_<0>, mpl::protect< mpl::next<> >
 185        , mpl::protect< find_fallback_type_pred >
 186        >::type first_result_;
 187
 188    typedef typename first_result_::first first_result_index;
 189    typedef typename first_result_::second first_result_it;
 190
 191    // [...now search the rest of the sequence for boost::blank...]
 192
 193    typedef typename mpl::iter_fold_if<
 194          mpl::iterator_range< first_result_it,end_it >
 195        , first_result_index, mpl::protect< mpl::next<> >
 196        , mpl::protect< mpl::not_same_as<boost::blank> >
 197        >::type second_result_;
 198
 199    typedef typename second_result_::second second_result_it;
 200
 201public: // metafunction result
 202
 203    // [...and return the results of the search:]
 204    typedef typename mpl::eval_if<
 205          is_same< second_result_it,end_it >
 206        , mpl::if_<
 207              is_same< first_result_it,end_it >
 208            , mpl::pair< no_fallback_type,no_fallback_type >
 209            , first_result_
 210            >
 211        , mpl::identity< second_result_ >
 212        >::type type;
 213
 214};
 215
 216#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
 217
 218template<>
 219struct find_fallback_type<int>
 220{
 221    typedef mpl::pair< no_fallback_type,no_fallback_type > type;
 222};
 223
 224#endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
 225
 226///////////////////////////////////////////////////////////////////////////////
 227// (detail) metafunction make_storage
 228//
 229// Provides an aligned storage type capable of holding any of the types
 230// specified in the given type-sequence.
 231//
 232
 233template <typename Types, typename NeverUsesBackupFlag>
 234struct make_storage
 235{
 236private: // helpers, for metafunction result (below)
 237
 238    typedef typename mpl::eval_if<
 239          NeverUsesBackupFlag
 240        , mpl::identity< Types >
 241        , mpl::push_front<
 242              Types, backup_holder<void*>
 243            >
 244        >::type types;
 245
 246    typedef typename max_value<
 247          types, mpl::sizeof_<mpl::_1>
 248        >::type max_size;
 249
 250#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
 251
 252    typedef typename mpl::fold<
 253          types
 254        , mpl::size_t<1>
 255        , add_alignment
 256        >::type max_alignment;
 257
 258#else // borland
 259
 260    // temporary workaround -- use maximal alignment
 261    typedef mpl::size_t< -1 > max_alignment;
 262
 263#endif // borland workaround
 264
 265public: // metafunction result
 266
 267#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
 268
 269    typedef ::boost::aligned_storage<
 270          BOOST_MPL_AUX_VALUE_WKND(max_size)::value
 271        , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
 272        > type;
 273
 274#else // MSVC7 and below
 275
 276    BOOST_STATIC_CONSTANT(std::size_t, msvc_max_size_c = max_size::value);
 277    BOOST_STATIC_CONSTANT(std::size_t, msvc_max_alignment_c = max_alignment::value);
 278
 279    typedef ::boost::aligned_storage<
 280          msvc_max_size_c
 281        , msvc_max_alignment_c
 282        > type;
 283
 284#endif // MSVC workaround
 285
 286};
 287
 288#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
 289
 290template<>
 291struct make_storage<int,int>
 292{
 293    typedef int type;
 294};
 295
 296#endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
 297
 298///////////////////////////////////////////////////////////////////////////////
 299// (detail) class destroyer
 300//
 301// Internal visitor that destroys the value it visits.
 302//
 303struct destroyer
 304    : public static_visitor<>
 305{
 306public: // visitor interfaces
 307
 308    template <typename T>
 309        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 310    internal_visit(T& operand, int) const
 311    {
 312        operand.~T();
 313
 314#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
 315    BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
 316        operand; // suppresses warnings
 317#endif
 318
 319        BOOST_VARIANT_AUX_RETURN_VOID;
 320    }
 321
 322};
 323
 324///////////////////////////////////////////////////////////////////////////////
 325// (detail) class template known_get
 326//
 327// Visitor that returns a reference to content of the specified type.
 328//
 329// Precondition: visited variant MUST contain logical content of type T.
 330//
 331template <typename T>
 332class known_get
 333    : public static_visitor<T&>
 334{
 335
 336#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 337
 338public: // visitor interface
 339
 340    T& operator()(T& operand) const
 341    {
 342        return operand;
 343    }
 344
 345    template <typename U>
 346    T& operator()(U&) const
 347    {
 348        // logical error to be here: see precondition above
 349        BOOST_ASSERT(false);
 350        return ::boost::detail::variant::forced_return< T& >();
 351    }
 352
 353#else // MSVC6
 354
 355private: // helpers, for visitor interface (below)
 356
 357    T& execute(T& operand, mpl::true_) const
 358    {
 359        return operand;
 360    }
 361
 362    template <typename U>
 363    T& execute(U& operand, mpl::false_) const
 364    {
 365        // logical error to be here: see precondition above
 366        BOOST_ASSERT(false);
 367        return ::boost::detail::variant::forced_return< T& >();
 368    }
 369
 370public: // visitor interface
 371
 372    template <typename U>
 373    T& operator()(U& operand) const
 374    {
 375        typedef typename is_same< U,T >::type
 376            U_is_T;
 377
 378        return execute(operand, U_is_T());
 379    }
 380
 381#endif // MSVC6 workaround
 382
 383};
 384
 385///////////////////////////////////////////////////////////////////////////////
 386// (detail) class copy_into
 387//
 388// Internal visitor that copies the value it visits into the given buffer.
 389//
 390class copy_into
 391    : public static_visitor<>
 392{
 393private: // representation
 394
 395    void* storage_;
 396
 397public: // structors
 398
 399    explicit copy_into(void* storage)
 400        : storage_(storage)
 401    {
 402    }
 403
 404public: // internal visitor interface
 405
 406    template <typename T>
 407        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 408    internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
 409    {
 410        new(storage_) T( operand.get() );
 411        BOOST_VARIANT_AUX_RETURN_VOID;
 412    }
 413
 414    template <typename T>
 415        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 416    internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
 417    {
 418        new(storage_) T( operand.get() );
 419        BOOST_VARIANT_AUX_RETURN_VOID;
 420    }
 421
 422    template <typename T>
 423        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 424    internal_visit(const T& operand, int) const
 425    {
 426        new(storage_) T(operand);
 427        BOOST_VARIANT_AUX_RETURN_VOID;
 428    }
 429
 430};
 431
 432///////////////////////////////////////////////////////////////////////////////
 433// (detail) class assign_storage
 434//
 435// Internal visitor that assigns the given storage (which must be a
 436// constructed value of the same type) to the value it visits.
 437//
 438struct assign_storage
 439    : public static_visitor<>
 440{
 441private: // representation
 442
 443    const void* rhs_storage_;
 444
 445public: // structors
 446
 447    explicit assign_storage(const void* rhs_storage)
 448        : rhs_storage_(rhs_storage)
 449    {
 450    }
 451
 452public: // internal visitor interfaces
 453
 454    template <typename T>
 455        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 456    internal_visit(backup_holder<T>& lhs_content, long) const
 457    {
 458        lhs_content.get()
 459            = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
 460        BOOST_VARIANT_AUX_RETURN_VOID;
 461    }
 462
 463    template <typename T>
 464        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 465    internal_visit(const backup_holder<T>& lhs_content, long) const
 466    {
 467        lhs_content.get()
 468            = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
 469        BOOST_VARIANT_AUX_RETURN_VOID;
 470    }
 471
 472    template <typename T>
 473        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 474    internal_visit(T& lhs_content, int) const
 475    {
 476        // NOTE TO USER :
 477        // Compile error here indicates one of variant's bounded types does
 478        // not meet the requirements of the Assignable concept. Thus,
 479        // variant is not Assignable.
 480        //
 481        // Hint: Are any of the bounded types const-qualified or references?
 482        //
 483        lhs_content = *static_cast< const T* >(rhs_storage_);
 484        BOOST_VARIANT_AUX_RETURN_VOID;
 485    }
 486
 487};
 488
 489///////////////////////////////////////////////////////////////////////////////
 490// (detail) class direct_assigner
 491//
 492// Generic static visitor that: if and only if the visited value is of the
 493// specified type, assigns the given value to the visited value and returns
 494// true; else returns false.
 495//
 496template <typename T>
 497class direct_assigner
 498    : public static_visitor<bool>
 499{
 500private: // representation
 501
 502    const T& rhs_;
 503
 504public: // structors
 505
 506    explicit direct_assigner(const T& rhs)
 507        : rhs_(rhs)
 508    {
 509    }
 510
 511#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 512
 513public: // visitor interface
 514
 515    bool operator()(T& lhs)
 516    {
 517        lhs = rhs_;
 518        return true;
 519    }
 520
 521    template <typename U>
 522    bool operator()(U&)
 523    {
 524        return false;
 525    }
 526
 527#else // MSVC6
 528
 529private: // helpers, for visitor interface (below)
 530
 531    bool execute(T& lhs, mpl::true_)
 532    {
 533        lhs = rhs_;
 534        return true;
 535    }
 536
 537    template <typename U>
 538    bool execute(U&, mpl::false_)
 539    {
 540        return false;
 541    }
 542
 543public: // visitor interface
 544
 545    template <typename U>
 546    bool operator()(U& lhs)
 547    {
 548        typedef typename is_same<U,T>::type U_is_T;
 549        return execute(lhs, U_is_T());
 550    }
 551
 552#endif // MSVC6 workaround
 553
 554#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
 555private:
 556    // silence MSVC warning C4512: assignment operator could not be generated
 557    direct_assigner& operator= (direct_assigner const&);
 558#endif
 559};
 560
 561///////////////////////////////////////////////////////////////////////////////
 562// (detail) class backup_assigner
 563//
 564// Internal visitor that "assigns" the given value to the visited value,
 565// using backup to recover if the destroy-copy sequence fails.
 566//
 567// NOTE: This needs to be a friend of variant, as it needs access to
 568// indicate_which, indicate_backup_which, etc.
 569//
 570template <typename Variant>
 571class backup_assigner
 572    : public static_visitor<>
 573{
 574private: // representation
 575
 576    Variant& lhs_;
 577    int rhs_which_;
 578    const void* rhs_content_;
 579    void (*copy_rhs_content_)(void*, const void*);
 580
 581public: // structors
 582
 583    template<class RhsT>
 584    backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
 585        : lhs_(lhs)
 586        , rhs_which_(rhs_which)
 587        , rhs_content_(&rhs_content)
 588        , copy_rhs_content_(&construct_impl<RhsT>)
 589    {
 590    }
 591
 592private: // helpers, for visitor interface (below)
 593
 594    template<class RhsT>
 595    static void construct_impl(void* addr, const void* obj)
 596    {
 597        new(addr) RhsT(*static_cast<const RhsT*>(obj));
 598    }
 599
 600    template <typename LhsT>
 601    void backup_assign_impl(
 602          LhsT& lhs_content
 603        , mpl::true_// has_nothrow_move
 604        )
 605    {
 606        // Move lhs content to backup...
 607        LhsT backup_lhs_content(
 608              ::boost::detail::variant::move(lhs_content)
 609            ); // nothrow
 610
 611        // ...destroy lhs content...
 612        lhs_content.~LhsT(); // nothrow
 613
 614        try
 615        {
 616            // ...and attempt to copy rhs content into lhs storage:
 617            copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
 618        }
 619        catch (...)
 620        {
 621            // In case of failure, restore backup content to lhs storage...
 622            new(lhs_.storage_.address())
 623                LhsT(
 624                      ::boost::detail::variant::move(backup_lhs_content)
 625                    ); // nothrow
 626
 627            // ...and rethrow:
 628            throw;
 629        }
 630
 631        // In case of success, indicate new content type:
 632        lhs_.indicate_which(rhs_which_); // nothrow
 633    }
 634
 635    template <typename LhsT>
 636    void backup_assign_impl(
 637          LhsT& lhs_content
 638        , mpl::false_// has_nothrow_move
 639        )
 640    {
 641        // Backup lhs content...
 642        LhsT* backup_lhs_ptr = new LhsT(lhs_content);
 643
 644        // ...destroy lhs content...
 645        lhs_content.~LhsT(); // nothrow
 646
 647        try
 648        {
 649            // ...and attempt to copy rhs content into lhs storage:
 650            copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
 651        }
 652        catch (...)
 653        {
 654            // In case of failure, copy backup pointer to lhs storage...
 655            new(lhs_.storage_.address())
 656                backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
 657
 658            // ...indicate now using backup...
 659            lhs_.indicate_backup_which( lhs_.which() ); // nothrow
 660
 661            // ...and rethrow:
 662            throw;
 663        }
 664
 665        // In case of success, indicate new content type...
 666        lhs_.indicate_which(rhs_which_); // nothrow
 667
 668        // ...and delete backup:
 669        delete backup_lhs_ptr; // nothrow
 670    }
 671
 672public: // visitor interface
 673
 674    template <typename LhsT>
 675        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 676    internal_visit(LhsT& lhs_content, int)
 677    {
 678        typedef typename has_nothrow_move_constructor<LhsT>::type
 679            nothrow_move;
 680
 681        backup_assign_impl( lhs_content, nothrow_move() );
 682
 683        BOOST_VARIANT_AUX_RETURN_VOID;
 684    }
 685
 686#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
 687private:
 688    // silence MSVC warning C4512: assignment operator could not be generated
 689    backup_assigner& operator= (backup_assigner const&);
 690#endif
 691};
 692
 693///////////////////////////////////////////////////////////////////////////////
 694// (detail) class swap_with
 695//
 696// Visitor that swaps visited value with content of given variant.
 697//
 698// Precondition: Given variant MUST have same logical type as visited value.
 699//
 700template <typename Variant>
 701struct swap_with
 702    : public static_visitor<>
 703{
 704private: // representation
 705
 706    Variant& toswap_;
 707
 708public: // structors
 709
 710    explicit swap_with(Variant& toswap)
 711        : toswap_(toswap)
 712    {
 713    }
 714
 715public: // internal visitor interfaces
 716
 717    template <typename T>
 718    void operator()(T& operand) const
 719    {
 720        // Since the precondition ensures types are same, get T...
 721        known_get<T> getter;
 722        T& other = toswap_.apply_visitor(getter);
 723
 724        // ...and swap:
 725        ::boost::detail::variant::move_swap( operand, other );
 726    }
 727
 728private:
 729    swap_with& operator=(const swap_with&);
 730
 731};
 732
 733///////////////////////////////////////////////////////////////////////////////
 734// (detail) class reflect
 735//
 736// Generic static visitor that performs a typeid on the value it visits.
 737//
 738
 739#if !defined(BOOST_NO_TYPEID)
 740
 741class reflect
 742    : public static_visitor<const std::type_info&>
 743{
 744public: // visitor interfaces
 745
 746    template <typename T>
 747    const std::type_info& operator()(const T&) const
 748    {
 749        return typeid(T);
 750    }
 751
 752};
 753
 754#endif // BOOST_NO_TYPEID
 755
 756///////////////////////////////////////////////////////////////////////////////
 757// (detail) class comparer
 758//
 759// Generic static visitor that compares the content of the given lhs variant
 760// with the visited rhs content using Comp.
 761//
 762// Precondition: lhs.which() == rhs.which()
 763//
 764template <typename Variant, typename Comp>
 765class comparer
 766    : public static_visitor<bool>
 767{
 768private: // representation
 769
 770    const Variant& lhs_;
 771
 772public: // structors
 773
 774    explicit comparer(const Variant& lhs)
 775        : lhs_(lhs)
 776    {
 777    }
 778
 779public: // visitor interfaces
 780
 781    template <typename T>
 782    bool operator()(const T& rhs_content) const
 783    {
 784        // Since the precondition ensures lhs and rhs types are same, get T...
 785        known_get<const T> getter;
 786        const T& lhs_content = lhs_.apply_visitor(getter);
 787
 788        // ...and compare lhs and rhs contents:
 789        return Comp()(lhs_content, rhs_content);
 790    }
 791
 792private:
 793    comparer& operator=(const comparer&);
 794
 795};
 796
 797///////////////////////////////////////////////////////////////////////////////
 798// (detail) class equal_comp
 799//
 800// Generic function object compares lhs with rhs using operator==.
 801//
 802struct equal_comp
 803{
 804    template <typename T>
 805    bool operator()(const T& lhs, const T& rhs) const
 806    {
 807        return lhs == rhs;
 808    }
 809};
 810
 811///////////////////////////////////////////////////////////////////////////////
 812// (detail) class less_comp
 813//
 814// Generic function object compares lhs with rhs using operator<.
 815//
 816struct less_comp
 817{
 818    template <typename T>
 819    bool operator()(const T& lhs, const T& rhs) const
 820    {
 821        return lhs < rhs;
 822    }
 823};
 824
 825///////////////////////////////////////////////////////////////////////////////
 826// (detail) class template invoke_visitor
 827//
 828// Internal visitor that invokes the given visitor using:
 829//  * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
 830//  * for all other values, the value itself.
 831//
 832template <typename Visitor>
 833class invoke_visitor
 834{
 835private: // representation
 836
 837    Visitor& visitor_;
 838
 839public: // visitor typedefs
 840
 841    typedef typename Visitor::result_type
 842        result_type;
 843
 844public: // structors
 845
 846    explicit invoke_visitor(Visitor& visitor)
 847        : visitor_(visitor)
 848    {
 849    }
 850
 851#if !defined(BOOST_NO_VOID_RETURNS)
 852
 853public: // internal visitor interfaces
 854
 855    template <typename T>
 856    result_type internal_visit(T& operand, int)
 857    {
 858        return visitor_(operand);
 859    }
 860
 861#   if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
 862    template <typename T>
 863    result_type internal_visit(const T& operand, int)
 864    {
 865        return visitor_(operand);
 866    }
 867#   endif
 868
 869#else // defined(BOOST_NO_VOID_RETURNS)
 870
 871private: // helpers, for internal visitor interfaces (below)
 872
 873    template <typename T>
 874        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 875    visit_impl(T& operand, mpl::false_)
 876    {
 877        return visitor_(operand);
 878    }
 879
 880    template <typename T>
 881        BOOST_VARIANT_AUX_RETURN_VOID_TYPE
 882    visit_impl(T& operand, mpl::true_)
 883    {
 884        visitor_(operand);
 885        BOOST_VARIANT_AUX_RETURN_VOID;
 886    }
 887
 888public: // internal visitor interfaces
 889
 890    template <typename T>
 891        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 892    internal_visit(T& operand, int)
 893    {
 894        typedef typename is_same<result_type, void>::type
 895            has_void_result_type;
 896
 897        return visit_impl(operand, has_void_result_type());
 898    }
 899
 900#endif // BOOST_NO_VOID_RETURNS) workaround
 901
 902public: // internal visitor interfaces, cont.
 903
 904    template <typename T>
 905        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 906    internal_visit(boost::recursive_wrapper<T>& operand, long)
 907    {
 908        return internal_visit( operand.get(), 1L );
 909    }
 910
 911    template <typename T>
 912        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 913    internal_visit(const boost::recursive_wrapper<T>& operand, long)
 914    {
 915        return internal_visit( operand.get(), 1L );
 916    }
 917
 918    template <typename T>
 919        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 920    internal_visit(boost::detail::reference_content<T>& operand, long)
 921    {
 922        return internal_visit( operand.get(), 1L );
 923    }
 924
 925    template <typename T>
 926        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 927    internal_visit(const boost::detail::reference_content<T>& operand, long)
 928    {
 929        return internal_visit( operand.get(), 1L );
 930    }
 931
 932    template <typename T>
 933        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 934    internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
 935    {
 936        return internal_visit( operand.get(), 1L );
 937    }
 938
 939    template <typename T>
 940        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
 941    internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
 942    {
 943        return internal_visit( operand.get(), 1L );
 944    }
 945
 946#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
 947private:
 948    // silence MSVC warning C4512: assignment operator could not be generated
 949    invoke_visitor& operator= (invoke_visitor const&);
 950#endif
 951};
 952
 953}} // namespace detail::variant
 954
 955///////////////////////////////////////////////////////////////////////////////
 956// class template variant (concept inspired by Andrei Alexandrescu)
 957//
 958// See docs and boost/variant/variant_fwd.hpp for more information.
 959//
 960template <
 961      typename T0_
 962    , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
 963    >
 964class variant
 965{
 966private: // helpers, for typedefs (below)
 967
 968    typedef variant wknd_self_t;
 969
 970    struct is_recursive_
 971        : detail::variant::is_recursive_flag<T0_>
 972    {
 973    };
 974
 975    typedef typename mpl::eval_if<
 976          is_recursive_
 977        , T0_
 978        , mpl::identity< T0_ >
 979        >::type unwrapped_T0_;
 980
 981    struct is_sequence_based_
 982        : detail::variant::is_over_sequence<unwrapped_T0_>
 983    {
 984    };
 985
 986#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
 987
 988private: // helpers, for typedefs (below)
 989
 990    typedef typename mpl::eval_if<
 991          is_sequence_based_
 992        , unwrapped_T0_ // over_sequence<...>::type
 993        , detail::variant::make_variant_list<
 994              unwrapped_T0_
 995            , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
 996            >
 997        >::type specified_types;
 998
 999    BOOST_STATIC_ASSERT((
1000          ::boost::mpl::not_< mpl::empty<specified_types> >::value
1001        ));
1002
1003    typedef typename mpl::eval_if<
1004          is_recursive_
1005        , mpl::transform<
1006              specified_types
1007            , mpl::protect<
1008                  detail::variant::quoted_enable_recursive<wknd_self_t>
1009                >
1010            >
1011        , mpl::identity< specified_types >
1012        >::type recursive_enabled_types;
1013
1014public: // public typedefs
1015
1016    typedef typename mpl::transform<
1017          recursive_enabled_types
1018        , unwrap_recursive<mpl::_1>
1019        >::type types;
1020
1021private: // internal typedefs
1022
1023    typedef typename mpl::transform<
1024          recursive_enabled_types
1025        , mpl::protect< detail::make_reference_content<> >
1026        >::type internal_types;
1027
1028    typedef typename mpl::front<
1029          internal_types
1030        >::type internal_T0;
1031
1032#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1033
1034private: // helpers, for typedefs (below)
1035
1036    typedef unwrapped_T0_ T0;
1037
1038    #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1039        typedef typename mpl::eval_if< \
1040              is_recursive_ \
1041            , detail::variant::enable_recursive< \
1042                  BOOST_PP_CAT(T,N) \
1043                , wknd_self_t \
1044                > \
1045            , mpl::identity< BOOST_PP_CAT(T,N) > \
1046            >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1047        /**/
1048
1049    BOOST_PP_REPEAT(
1050          BOOST_VARIANT_LIMIT_TYPES
1051        , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1052        , _
1053        )
1054
1055    #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1056
1057    #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1058        typedef typename unwrap_recursive< \
1059              BOOST_PP_CAT(recursive_enabled_T,N) \
1060            >::type BOOST_PP_CAT(public_T,N); \
1061        /**/
1062
1063    BOOST_PP_REPEAT(
1064          BOOST_VARIANT_LIMIT_TYPES
1065        , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1066        , _
1067        )
1068
1069    #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1070
1071public: // public typedefs
1072
1073    typedef typename detail::variant::make_variant_list<
1074          BOOST_VARIANT_ENUM_PARAMS(public_T)
1075        >::type types;
1076
1077private: // helpers, for internal typedefs (below)
1078
1079    #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1080        typedef detail::make_reference_content< \
1081              BOOST_PP_CAT(recursive_enabled_T,N) \
1082            >::type BOOST_PP_CAT(internal_T,N); \
1083        /**/
1084
1085    BOOST_PP_REPEAT(
1086          BOOST_VARIANT_LIMIT_TYPES
1087        , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1088        , _
1089        )
1090
1091    #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1092
1093private: // internal typedefs
1094
1095    typedef typename detail::variant::make_variant_list<
1096          BOOST_VARIANT_ENUM_PARAMS(internal_T)
1097        >::type internal_types;
1098
1099private: // static precondition assertions
1100
1101    // NOTE TO USER :
1102    // variant< type-sequence > syntax is not supported on this compiler!
1103    //
1104    BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1105
1106#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1107
1108private: // helpers, for representation (below)
1109
1110    typedef typename detail::variant::find_fallback_type<
1111          internal_types
1112        >::type fallback_type_result_;
1113
1114    typedef typename fallback_type_result_::first
1115        fallback_type_index_;
1116    typedef typename fallback_type_result_::second
1117        fallback_type_;
1118
1119    struct has_fallback_type_
1120        : mpl::not_<
1121              is_same< fallback_type_, detail::variant::no_fallback_type >
1122            >
1123    {
1124    };
1125
1126    typedef has_fallback_type_
1127        never_uses_backup_flag;
1128
1129    typedef typename detail::variant::make_storage<
1130          internal_types, never_uses_backup_flag
1131        >::type storage_t;
1132
1133private: // helpers, for representation (below)
1134
1135    // which_ on:
1136    // * [0,  size<internal_types>) indicates stack content
1137    // * [-size<internal_types>, 0) indicates pointer to heap backup
1138    // if which_ >= 0:
1139    // * then which() -> which_
1140    // * else which() -> -(which_ + 1)
1141
1142#if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1143
1144    typedef int which_t;
1145
1146#else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1147
1148    // [if O1_size available, then attempt which_t size optimization...]
1149    // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1150    typedef typename mpl::eval_if<
1151          mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1152        , mpl::identity< int >
1153        , mpl::if_<
1154              mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1155            , signed char
1156            , int
1157            >
1158        >::type which_t;
1159
1160#endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1161
1162// representation -- private when possible
1163#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1164    private:
1165#else
1166    public:
1167#endif
1168
1169    which_t which_;
1170    storage_t storage_;
1171
1172    void indicate_which(int which_arg)
1173    {
1174        which_ = static_cast<which_t>( which_arg );
1175    }
1176
1177    void indicate_backup_which(int which_arg)
1178    {
1179        which_ = static_cast<which_t>( -(which_arg + 1) );
1180    }
1181
1182private: // helpers, for queries (below)
1183
1184    bool using_backup() const
1185    {
1186        return which_ < 0;
1187    }
1188
1189public: // queries
1190
1191    int which() const
1192    {
1193        // If using heap backup...
1194        if (using_backup())
1195            // ...then return adjusted which_:
1196            return -(which_ + 1);
1197
1198        // Otherwise, return which_ directly:
1199        return which_;
1200    }
1201
1202private: // helpers, for structors (below)
1203
1204    struct initializer
1205        : BOOST_VARIANT_AUX_INITIALIZER_T(
1206              recursive_enabled_types, recursive_enabled_T
1207            )
1208    {
1209    };
1210
1211    void destroy_content()
1212    {
1213        detail::variant::destroyer visitor;
1214        this->internal_apply_visitor(visitor);
1215    }
1216
1217public: // structors
1218
1219    ~variant()
1220    {
1221        destroy_content();
1222    }
1223
1224    variant()
1225    {
1226        // NOTE TO USER :
1227        // Compile error from here indicates that the first bound
1228        // type is not default-constructible, and so variant cannot
1229        // support its own default-construction.
1230        //
1231        new( storage_.address() ) internal_T0();
1232        indicate_which(0); // zero is the index of the first bounded type
1233    }
1234
1235private: // helpers, for structors, cont. (below)
1236
1237    class convert_copy_into
1238        : public static_visitor<int>
1239    {
1240    private: // representation
1241
1242        void* storage_;
1243
1244    public: // structors
1245
1246        explicit convert_copy_into(void* storage)
1247            : storage_(storage)
1248        {
1249        }
1250
1251    public: // internal visitor interfaces (below)
1252
1253        template <typename T>
1254        int internal_visit(T& operand, int) const
1255        {
1256            // NOTE TO USER :
1257            // Compile error here indicates one of the source variant's types 
1258            // cannot be unambiguously converted to the destination variant's
1259            // types (or that no conversion exists).
1260            //
1261            return initializer::initialize(storage_, operand);
1262        }
1263
1264#   if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1265        template <typename T>
1266        result_type internal_visit(const T& operand, int) const
1267        {
1268            return initializer::initialize(storage_, operand);
1269        }
1270#   endif
1271
1272        template <typename T>
1273        int internal_visit(boost::detail::reference_content<T>& operand, long) const
1274        {
1275            return internal_visit( operand.get(), 1L );
1276        }
1277
1278        template <typename T>
1279        int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1280        {
1281            return internal_visit( operand.get(), 1L );
1282        }
1283
1284        template <typename T>
1285        int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1286        {
1287            return internal_visit( operand.get(), 1L );
1288        }
1289
1290        template <typename T>
1291        int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1292        {
1293            return internal_visit( operand.get(), 1L );
1294        }
1295
1296        template <typename T>
1297        int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1298        {
1299            return internal_visit( operand.get(), 1L );
1300        }
1301
1302        template <typename T>
1303        int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1304        {
1305            return internal_visit( operand.get(), 1L );
1306        }
1307
1308    };
1309
1310    friend class convert_copy_into;
1311
1312private: // helpers, for structors, below 
1313
1314    template <typename T>
1315    void convert_construct(
1316          T& operand
1317        , int
1318        , mpl::false_ = mpl::false_() // is_foreign_variant
1319        )
1320    {
1321        // NOTE TO USER :
1322        // Compile error here indicates that the given type is not 
1323        // unambiguously convertible to one of the variant's types
1324        // (or that no conversion exists).
1325        //
1326        indicate_which(
1327              initializer::initialize(
1328                  storage_.address()
1329                , operand
1330                )
1331            );
1332    }
1333
1334    template <typename Variant>
1335    void convert_construct(
1336          Variant& operand
1337        , long
1338        , mpl::true_// is_foreign_variant
1339        )
1340    {
1341        convert_copy_into visitor(storage_.address());
1342        indicate_which(
1343              operand.internal_apply_visitor(visitor)
1344            );
1345    }
1346
1347    template <typename Variant>
1348    void convert_construct_variant(Variant& operand)
1349    {
1350        // [Determine if the given variant is itself a bounded type, or if its
1351        //  content needs to be converted (i.e., it is a 'foreign' variant):]
1352        //
1353
1354        typedef typename mpl::find_if<
1355              types
1356            , is_same<
1357                  add_const<mpl::_1>
1358                , const Variant
1359                >
1360            >::type found_it;
1361
1362        typedef typename mpl::end<types>::type not_found;
1363        typedef typename is_same<
1364              found_it, not_found
1365            >::type is_foreign_variant;
1366
1367        // Convert construct from operand:
1368        convert_construct(
1369              operand, 1L
1370            , is_foreign_variant()
1371            );
1372    }
1373
1374    template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1375    void convert_construct(
1376          boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1377        , long
1378        )
1379    {
1380        convert_construct_variant(operand);
1381    }
1382
1383    template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1384    void convert_construct(
1385          const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1386        , long
1387        )
1388    {
1389        convert_construct_variant(operand);    
1390    }
1391
1392public: // structors, cont.
1393
1394#if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
1395
1396    template <typename T>
1397    variant(const T& operand)
1398    {
1399        convert_construct(operand, 1L);
1400    }
1401
1402    template <typename T>
1403    variant(T& operand)
1404    {
1405        convert_construct(operand, 1L);
1406    }
1407
1408#elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1409
1410    // For compilers that cannot distinguish between T& and const T& in
1411    // template constructors, but do fully support SFINAE, we can workaround:
1412
1413    template <typename T>
1414    variant(const T& operand)
1415    {
1416        convert_construct(operand, 1L);
1417    }
1418
1419    template <typename T>
1420    variant(
1421          T& operand
1422        , typename enable_if<
1423              mpl::not_< is_const<T> >
1424            , void
1425            >::type* = 0
1426        )
1427    {
1428        convert_construct(operand, 1L);
1429    }
1430
1431#else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1432
1433    // For compilers that cannot distinguish between T& and const T& in
1434    // template constructors, and do NOT support SFINAE, we can't workaround:
1435
1436    template <typename T>
1437    variant(const T& operand)
1438    {
1439        convert_construct(operand, 1L);
1440    }
1441
1442#endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
1443
1444public: // structors, cont.
1445
1446    // [MSVC6 requires copy constructor appear after template constructors]
1447    variant(const variant& operand)
1448    {
1449        // Copy the value of operand into *this...
1450        detail::variant::copy_into visitor( storage_.address() );
1451        operand.internal_apply_visitor(visitor);
1452
1453        // ...and activate the *this's primary storage on success:
1454        indicate_which(operand.which());
1455    }
1456
1457private: // helpers, for modifiers (below)
1458
1459#   if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1460    template <typename Variant>
1461    friend class detail::variant::backup_assigner;
1462#   endif
1463
1464    // class assigner
1465    //
1466    // Internal visitor that "assigns" the visited value to the given variant
1467    // by appropriate destruction and copy-construction.
1468    //
1469
1470    class assigner
1471        : public static_visitor<>
1472    {
1473    private: // representation
1474
1475        variant& lhs_;
1476        int rhs_which_;
1477
1478    public: // structors
1479
1480        assigner(variant& lhs, int rhs_which)
1481            : lhs_(lhs)
1482            , rhs_which_(rhs_which)
1483        {
1484        }
1485
1486    private: // helpers, for internal visitor interface (below)
1487
1488        template <typename RhsT, typename B1, typename B2>
1489        void assign_impl(
1490              const RhsT& rhs_content
1491            , mpl::true_// has_nothrow_copy
1492            , B1// has_nothrow_move_constructor
1493            , B2// has_fallback_type
1494            )
1495        {
1496            // Destroy lhs's content...
1497            lhs_.destroy_content(); // nothrow
1498
1499            // ...copy rhs content into lhs's storage...
1500            new(lhs_.storage_.address())
1501                RhsT( rhs_content ); // nothrow
1502
1503            // ...and indicate new content type:
1504            lhs_.indicate_which(rhs_which_); // nothrow
1505        }
1506
1507        template <typename RhsT, typename B>
1508        void assign_impl(
1509              const RhsT& rhs_content
1510            , mpl::false_// has_nothrow_copy
1511            , mpl::true_// has_nothrow_move_constructor
1512            , B// has_fallback_type
1513            )
1514        {
1515            // Attempt to make a temporary copy (so as to move it below)...
1516            RhsT temp(rhs_content);
1517
1518            // ...and upon success destroy lhs's content...
1519            lhs_.destroy_content(); // nothrow
1520
1521            // ...move the temporary copy into lhs's storage...
1522            new(lhs_.storage_.address())
1523                RhsT( detail::variant::move(temp) ); // nothrow
1524
1525            // ...and indicate new content type:
1526            lhs_.indicate_which(rhs_which_); // nothrow
1527        }
1528
1529        template <typename RhsT>
1530        void assign_impl(
1531              const RhsT& rhs_content
1532            , mpl::false_// has_nothrow_copy
1533            , mpl::false_// has_nothrow_move_constructor
1534            , mpl::true_// has_fallback_type
1535            )
1536        {
1537            // Destroy lhs's content...
1538            lhs_.destroy_content(); // nothrow
1539
1540            try
1541            {
1542                // ...and attempt to copy rhs's content into lhs's storage:
1543                new(lhs_.storage_.address())
1544                    RhsT( rhs_content );
1545            }
1546            catch (...)
1547            {
1548                // In case of failure, default-construct fallback type in lhs's storage...
1549                new (lhs_.storage_.address())
1550                    fallback_type_; // nothrow
1551
1552                // ...indicate construction of fallback type...
1553                lhs_.indicate_which(
1554                      BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1555                    ); // nothrow
1556
1557                // ...and rethrow:
1558                throw;
1559            }
1560
1561            // In the event of success, indicate new content type:
1562            lhs_.indicate_which(rhs_which_); // nothrow
1563        }
1564
1565        template <typename RhsT>
1566        void assign_impl(
1567              const RhsT& rhs_content
1568            , mpl::false_// has_nothrow_copy
1569            , mpl::false_// has_nothrow_move_constructor
1570            , mpl::false_// has_fallback_type
1571            )
1572        {
1573            detail::variant::backup_assigner<wknd_self_t>
1574                visitor(lhs_, rhs_which_, rhs_content);
1575            lhs_.internal_apply_visitor(visitor);
1576        }
1577
1578    public: // internal visitor interfaces
1579
1580        template <typename RhsT>
1581            BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1582        internal_visit(const RhsT& rhs_content, int)
1583        {
1584            typedef typename has_nothrow_copy<RhsT>::type
1585                nothrow_copy;
1586            typedef typename mpl::or_< // reduces compile-time
1587                  nothrow_copy
1588                , detail::variant::has_nothrow_move_constructor<RhsT>
1589                >::type nothrow_move_constructor;
1590
1591            assign_impl(
1592                  rhs_content
1593                , nothrow_copy()
1594                , nothrow_move_constructor()
1595                , has_fallback_type_()
1596                );
1597
1598            BOOST_VARIANT_AUX_RETURN_VOID;
1599        }
1600
1601#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1602    private:
1603        // silence MSVC warning C4512: assignment operator could not be generated
1604        assigner& operator= (assigner const&);
1605#endif
1606    };
1607
1608    friend class assigner;
1609
1610    void variant_assign(const variant& rhs)
1611    {
1612        // If the contained types are EXACTLY the same...
1613        if (which_ == rhs.which_)
1614        {
1615            // ...then assign rhs's storage to lhs's content:
1616            detail::variant::assign_storage visitor(rhs.storage_.address());
1617            this->internal_apply_visitor(visitor);
1618        }
1619        else
1620        {
1621            // Otherwise, perform general (copy-based) variant assignment:
1622            assigner visitor(*this, rhs.which());
1623            rhs.internal_apply_visitor(visitor); 
1624        }
1625    }
1626
1627private: // helpers, for modifiers (below)
1628
1629    template <typename T>
1630    void assign(const T& rhs)
1631    {
1632        // If direct T-to-T assignment is not possible...
1633        detail::variant::direct_assigner<T> direct_assign(rhs);
1634        if (this->apply_visitor(direct_assign) == false)
1635        {
1636            // ...then convert rhs to variant and assign:
1637            //
1638            // While potentially inefficient, the following construction of a
1639            // variant allows T as any type convertible to one of the bounded
1640            // types without excessive code redundancy.
1641            //
1642            variant temp(rhs);
1643            variant_assign( detail::variant::move(temp) );
1644        }
1645    }
1646
1647public: // modifiers
1648
1649    template <typename T>
1650    variant& operator=(const T& rhs)
1651    {
1652        assign(rhs);
1653        return *this;
1654    }
1655
1656    // [MSVC6 requires copy assign appear after templated operator=]
1657    variant& operator=(const variant& rhs)
1658    {
1659        variant_assign(rhs);
1660        return *this;
1661    }
1662
1663    void swap(variant& rhs)
1664    {
1665        // If the contained types are the same...
1666        if (which() == rhs.which())
1667        {
1668            // ...then swap the values directly:
1669            detail::variant::swap_with<variant> visitor(rhs);
1670            this->apply_visitor(visitor);
1671        }
1672        else
1673        {
1674            // ...otherwise, perform general variant swap:
1675            variant tmp( detail::variant::move(rhs) );
1676            rhs = detail::variant::move(*this);
1677            *this = detail::variant::move(tmp);
1678        }
1679    }
1680
1681public: // queries
1682
1683    //
1684    // NOTE: member which() defined above.
1685    //
1686
1687    bool empty() const
1688    {
1689        return false;
1690    }
1691
1692#if !defined(BOOST_NO_TYPEID)
1693    const std::type_info& type() const
1694    {
1695        detail::variant::reflect visitor;
1696        return this->apply_visitor(visitor);
1697    }
1698#endif
1699
1700public: // prevent comparison with foreign types
1701
1702#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1703
1704#   define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1705    void
1706
1707#else // MSVC7
1708
1709    //
1710    // MSVC7 gives error about return types for above being different than
1711    // the true comparison operator overloads:
1712    //
1713
1714#   define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1715    bool
1716
1717#endif // MSVC7 workaround
1718
1719    template <typename U>
1720        BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1721    operator==(const U&) const
1722    {
1723        BOOST_STATIC_ASSERT( false && sizeof(U) );
1724    }
1725
1726    template <typename U>
1727        BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1728    operator<(const U&) const
1729    {
1730        BOOST_STATIC_ASSERT( false && sizeof(U) );
1731    }
1732
1733public: // comparison operators
1734
1735    // [MSVC6 requires these operators appear after template operators]
1736
1737    bool operator==(const variant& rhs) const
1738    {
1739        if (this->which() != rhs.which())
1740            return false;
1741
1742        detail::variant::comparer<
1743              variant, detail::variant::equal_comp
1744            > visitor(*this);
1745        return rhs.apply_visitor(visitor);
1746    }
1747
1748    bool operator<(const variant& rhs) const
1749    {
1750        //
1751        // Dirk Schreib suggested this collating order.
1752        //
1753
1754        if (this->which() != rhs.which())
1755            return this->which() < rhs.which();
1756
1757        detail::variant::comparer<
1758              variant, detail::variant::less_comp
1759            > visitor(*this);
1760        return rhs.apply_visitor(visitor);
1761    }
1762
1763// helpers, for visitation support (below) -- private when possible
1764#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1765
1766    template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
1767    friend class variant;
1768
1769private:
1770
1771#else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1772
1773public:
1774
1775#endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1776
1777    template <typename Visitor, typename VoidPtrCV>
1778    static
1779        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1780              typename Visitor::result_type
1781            )
1782    internal_apply_visitor_impl(
1783          int internal_which
1784        , int logical_which
1785        , Visitor& visitor
1786        , VoidPtrCV storage
1787        )
1788    {
1789        typedef mpl::int_<0> first_which;
1790        typedef typename mpl::begin<internal_types>::type first_it;
1791        typedef typename mpl::end<internal_types>::type last_it;
1792
1793        typedef detail::variant::visitation_impl_step<
1794              first_it, last_it
1795            > first_step;
1796
1797        return detail::variant::visitation_impl(
1798              internal_which, logical_which
1799            , visitor, storage, mpl::false_()
1800            , never_uses_backup_flag()
1801            , static_cast<first_which*>(0), static_cast<first_step*>(0)
1802            );
1803    }
1804
1805    template <typename Visitor>
1806        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1807              typename Visitor::result_type
1808            )
1809    internal_apply_visitor(Visitor& visitor)
1810    {
1811        return internal_apply_visitor_impl(
1812              which_, which(), visitor, storage_.address()
1813            );
1814    }
1815
1816    template <typename Visitor>
1817        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1818              typename Visitor::result_type
1819            )
1820    internal_apply_visitor(Visitor& visitor) const
1821    {
1822        return internal_apply_visitor_impl(
1823              which_, which(), visitor, storage_.address()
1824            );
1825    }
1826
1827public: // visitation support
1828
1829    template <typename Visitor>
1830        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1831              typename Visitor::result_type
1832            )
1833    apply_visitor(Visitor& visitor)
1834    {
1835        detail::variant::invoke_visitor<Visitor> invoker(visitor);
1836        return this->internal_apply_visitor(invoker);
1837    }
1838
1839    template <typename Visitor>
1840        BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1841              typename Visitor::result_type
1842            )
1843    apply_visitor(Visitor& visitor) const
1844    {
1845        detail::variant::invoke_visitor<Visitor> invoker(visitor);
1846        return this->internal_apply_visitor(invoker);
1847    }
1848
1849}; // class variant
1850
1851///////////////////////////////////////////////////////////////////////////////
1852// metafunction make_variant_over
1853//
1854// See docs and boost/variant/variant_fwd.hpp for more information.
1855//
1856template <typename Types>
1857struct make_vari

Large files files are truncated, but you can click here to view the full file