source: NonGTP/Boost/boost/variant/variant.hpp @ 857

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