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