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