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 Eric Friedman, Itay Maman
7 // Copyright (c) 2012-2014 Antony Polukhin
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 // Thanks to Adam Romanek for providing patches for exception-disabled env.
14 
15 #ifndef BOOST_VARIANT_VARIANT_HPP
16 #define BOOST_VARIANT_VARIANT_HPP
17 
18 #include <cstddef> // for std::size_t
19 #include <new> // for placement new
20 
21 #include "boost/type_index.hpp"
22 
23 #include "boost/variant/detail/config.hpp"
24 #include "boost/mpl/aux_/value_wknd.hpp"
25 
26 #include "boost/variant/variant_fwd.hpp"
27 #include "boost/variant/detail/backup_holder.hpp"
28 #include "boost/variant/detail/enable_recursive_fwd.hpp"
29 #include "boost/variant/detail/forced_return.hpp"
30 #include "boost/variant/detail/initializer.hpp"
31 #include "boost/variant/detail/make_variant_list.hpp"
32 #include "boost/variant/detail/over_sequence.hpp"
33 #include "boost/variant/detail/visitation_impl.hpp"
34 #include "boost/variant/detail/hash_variant.hpp"
35 
36 #include "boost/variant/detail/generic_result_type.hpp"
37 #include "boost/variant/detail/move.hpp"
38 
39 #include "boost/detail/no_exceptions_support.hpp"
40 #include "boost/detail/reference_content.hpp"
41 #include "boost/aligned_storage.hpp"
42 #include "boost/blank.hpp"
43 #include "boost/math/common_factor_ct.hpp"
44 #include "boost/static_assert.hpp"
45 #include "boost/preprocessor/cat.hpp"
46 #include "boost/preprocessor/repeat.hpp"
47 #include "boost/type_traits/alignment_of.hpp"
48 #include "boost/type_traits/add_const.hpp"
49 #include "boost/type_traits/has_nothrow_constructor.hpp"
50 #include "boost/type_traits/has_nothrow_copy.hpp"
51 #include "boost/type_traits/is_nothrow_move_assignable.hpp"
52 #include "boost/type_traits/is_nothrow_move_constructible.hpp"
53 #include "boost/type_traits/is_const.hpp"
54 #include "boost/type_traits/is_same.hpp"
55 #include "boost/type_traits/is_rvalue_reference.hpp"
56 #include "boost/utility/enable_if.hpp"
57 #include "boost/utility/declval.hpp"
58 #include "boost/variant/recursive_wrapper_fwd.hpp"
59 #include "boost/variant/static_visitor.hpp"
60 
61 #include "boost/mpl/assert.hpp"
62 #include "boost/mpl/begin_end.hpp"
63 #include "boost/mpl/bool.hpp"
64 #include "boost/mpl/deref.hpp"
65 #include "boost/mpl/empty.hpp"
66 #include "boost/mpl/eval_if.hpp"
67 #include "boost/mpl/find_if.hpp"
68 #include "boost/mpl/fold.hpp"
69 #include "boost/mpl/front.hpp"
70 #include "boost/mpl/identity.hpp"
71 #include "boost/mpl/if.hpp"
72 #include "boost/mpl/int.hpp"
73 #include "boost/mpl/is_sequence.hpp"
74 #include "boost/mpl/iterator_range.hpp"
75 #include "boost/mpl/iter_fold_if.hpp"
76 #include "boost/mpl/logical.hpp"
77 #include "boost/mpl/max_element.hpp"
78 #include "boost/mpl/next.hpp"
79 #include "boost/mpl/not.hpp"
80 #include "boost/mpl/pair.hpp"
81 #include "boost/mpl/protect.hpp"
82 #include "boost/mpl/push_front.hpp"
83 #include "boost/mpl/same_as.hpp"
84 #include "boost/mpl/size_t.hpp"
85 #include "boost/mpl/sizeof.hpp"
86 #include "boost/mpl/transform.hpp"
87 
88 ///////////////////////////////////////////////////////////////////////////////
89 // Implementation Macros:
90 //
91 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
92 //   Defined in boost/variant/detail/visitation_impl.hpp.
93 //
94 // BOOST_VARIANT_MINIMIZE_SIZE
95 //   When #defined, implementation employs all known means to minimize the
96 //   size of variant obje   cts. However, often unsuccessful due to alignment
97 //   issues, and potentially harmful to runtime speed, so not enabled by
98 //   default. (TODO: Investigate further.)
99 
100 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
101 #   include <climits> // for SCHAR_MAX
102 #   include "boost/mpl/eval_if.hpp"
103 #   include "boost/mpl/equal_to.hpp"
104 #   include "boost/mpl/identity.hpp"
105 #   include "boost/mpl/int.hpp"
106 #   include "boost/mpl/if.hpp"
107 #   include "boost/mpl/less.hpp"
108 #   include "boost/mpl/long.hpp"
109 #   include "boost/mpl/O1_size.hpp"
110 #endif
111 
112 
113 namespace boost {
114 
115 namespace detail { namespace variant {
116 
117 ///////////////////////////////////////////////////////////////////////////////
118 // (detail) metafunction max_value
119 //
120 // Finds the maximum value of the unary metafunction F over Sequence.
121 //
122 template <typename Sequence, typename F>
123 struct max_value
124 {
125 private: // helpers, for metafunction result (below)
126 
127     typedef typename mpl::transform1<Sequence, F>::type transformed_;
128     typedef typename mpl::max_element<transformed_
129 
130         >::type max_it;
131 
132 public: // metafunction result
133 
134     typedef typename mpl::deref<max_it>::type
135         type;
136 
137 };
138 
139 struct add_alignment
140 {
141     template <typename State, typename Item>
142     struct apply
143         : mpl::size_t<
144               ::boost::math::static_lcm<
145                   BOOST_MPL_AUX_VALUE_WKND(State)::value
146                 , ::boost::alignment_of<Item>::value
147                 >::value
148             >
149     {};
150 };
151 
152 ///////////////////////////////////////////////////////////////////////////////
153 // (detail) metafunction find_fallback_type
154 //
155 // Provides a fallback (i.e., nothrow default-constructible) type from the
156 // specified sequence, or no_fallback_type if not found.
157 //
158 // This implementation is designed to prefer boost::blank over other potential
159 // fallback types, regardless of its position in the specified sequence.
160 //
161 
162 class no_fallback_type;
163 
164 struct find_fallback_type_pred
165 {
166     template <typename Iterator>
167     struct apply
168     {
169     private:
170         typedef typename mpl::deref<Iterator>::type t_;
171 
172     public:
173         typedef mpl::not_< has_nothrow_constructor<t_> > type;
174     };
175 };
176 
177 template <typename Types>
178 struct find_fallback_type
179 {
180 private: // helpers, for metafunction result (below)
181 
182     typedef typename mpl::end<Types>::type end_it;
183 
184     // [Find the first suitable fallback type...]
185 
186     typedef typename mpl::iter_fold_if<
187           Types
188         , mpl::int_<0>, mpl::protect< mpl::next<> >
189         , mpl::protect< find_fallback_type_pred >
190         >::type first_result_;
191 
192     typedef typename first_result_::first first_result_index;
193     typedef typename first_result_::second first_result_it;
194 
195     // [...now search the rest of the sequence for boost::blank...]
196 
197     typedef typename mpl::iter_fold_if<
198           mpl::iterator_range< first_result_it,end_it >
199         , first_result_index, mpl::protect< mpl::next<> >
200         , mpl::protect< mpl::not_same_as<boost::blank> >
201         >::type second_result_;
202 
203     typedef typename second_result_::second second_result_it;
204 
205 public: // metafunction result
206 
207     // [...and return the results of the search:]
208     typedef typename mpl::eval_if<
209           is_same< second_result_it,end_it >
210         , mpl::if_<
211               is_same< first_result_it,end_it >
212             , mpl::pair< no_fallback_type,no_fallback_type >
213             , first_result_
214             >
215         , mpl::identity< second_result_ >
216         >::type type;
217 
218 };
219 
220 #ifndef BOOST_NO_CXX11_NOEXCEPT
221 ///////////////////////////////////////////////////////////////////////////////
222 // (detail) metafunction is_variant_move_noexcept_constructible
223 //
224 // Returns true_type if all the types are nothrow move constructible.
225 //
226 template <class Types>
227 struct is_variant_move_noexcept_constructible {
228     typedef typename boost::mpl::find_if<
229         Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
230     >::type iterator_t;
231 
232     typedef typename boost::mpl::end<Types>::type end_t;
233     typedef typename boost::is_same<
234         iterator_t, end_t
235     >::type type;
236 };
237 
238 ///////////////////////////////////////////////////////////////////////////////
239 // (detail) metafunction is_variant_move_noexcept_assignable
240 //
241 // Returns true_type if all the types are nothrow move constructible.
242 //
243 template <class Types>
244 struct is_variant_move_noexcept_assignable {
245     typedef typename boost::mpl::find_if<
246         Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
247     >::type iterator_t;
248 
249     typedef typename boost::mpl::end<Types>::type end_t;
250     typedef typename boost::is_same<
251         iterator_t, end_t
252     >::type type;
253 };
254 #endif // BOOST_NO_CXX11_NOEXCEPT
255 
256 ///////////////////////////////////////////////////////////////////////////////
257 // (detail) metafunction make_storage
258 //
259 // Provides an aligned storage type capable of holding any of the types
260 // specified in the given type-sequence.
261 //
262 
263 template <typename Types, typename NeverUsesBackupFlag>
264 struct make_storage
265 {
266 private: // helpers, for metafunction result (below)
267 
268     typedef typename mpl::eval_if<
269           NeverUsesBackupFlag
270         , mpl::identity< Types >
271         , mpl::push_front<
272               Types, backup_holder<void*>
273             >
274         >::type types;
275 
276     typedef typename max_value<
277           types, mpl::sizeof_<mpl::_1>
278         >::type max_size;
279 
280 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
281 
282     typedef typename mpl::fold<
283           types
284         , mpl::size_t<1>
285         , add_alignment
286         >::type max_alignment;
287 
288 #else // borland
289 
290     // temporary workaround -- use maximal alignment
291     typedef mpl::size_t< -1 > max_alignment;
292 
293 #endif // borland workaround
294 
295 public: // metafunction result
296 
297     typedef ::boost::aligned_storage<
298           BOOST_MPL_AUX_VALUE_WKND(max_size)::value
299         , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
300         > type;
301 };
302 
303 ///////////////////////////////////////////////////////////////////////////////
304 // (detail) class destroyer
305 //
306 // Internal visitor that destroys the value it visits.
307 //
308 struct destroyer
309     : public static_visitor<>
310 {
311 public: // visitor interfaces
312 
313     template <typename T>
314         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::destroyer315     internal_visit(T& operand, int) const BOOST_NOEXCEPT
316     {
317         operand.~T(); // must be noexcept
318 
319 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
320     BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
321         operand; // suppresses warnings
322 #endif
323 
324         BOOST_VARIANT_AUX_RETURN_VOID;
325     }
326 
327 };
328 
329 ///////////////////////////////////////////////////////////////////////////////
330 // (detail) class template known_get
331 //
332 // Visitor that returns a reference to content of the specified type.
333 //
334 // Precondition: visited variant MUST contain logical content of type T.
335 //
336 template <typename T>
337 class known_get
338     : public static_visitor<T&>
339 {
340 
341 public: // visitor interface
342 
operator ()(T & operand) const343     T& operator()(T& operand) const BOOST_NOEXCEPT
344     {
345         return operand;
346     }
347 
348     template <typename U>
operator ()(U &) const349     T& operator()(U&) const
350     {
351         // logical error to be here: see precondition above
352         return ::boost::detail::variant::forced_return< T& >();
353     }
354 };
355 
356 ///////////////////////////////////////////////////////////////////////////////
357 // (detail) class copy_into
358 //
359 // Internal visitor that copies the value it visits into the given buffer.
360 //
361 class copy_into
362     : public static_visitor<>
363 {
364 private: // representation
365 
366     void* storage_;
367 
368 public: // structors
369 
copy_into(void * storage)370     explicit copy_into(void* storage) BOOST_NOEXCEPT
371         : storage_(storage)
372     {
373     }
374 
375 public: // internal visitor interface
376 
377     template <typename T>
378         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const379     internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
380     {
381         new(storage_) T( operand.get() );
382         BOOST_VARIANT_AUX_RETURN_VOID;
383     }
384 
385     template <typename T>
386         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const387     internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
388     {
389         new(storage_) T( operand.get() );
390         BOOST_VARIANT_AUX_RETURN_VOID;
391     }
392 
393     template <typename T>
394         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(const T & operand,int) const395     internal_visit(const T& operand, int) const
396     {
397         new(storage_) T(operand);
398         BOOST_VARIANT_AUX_RETURN_VOID;
399     }
400 
401 };
402 
403 ///////////////////////////////////////////////////////////////////////////////
404 // (detail) class move_into
405 //
406 // Internal visitor that moves the value it visits into the given buffer.
407 //
408 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
409 class move_into
410     : public static_visitor<>
411 {
412 private: // representation
413 
414     void* storage_;
415 
416 public: // structors
417 
move_into(void * storage)418     explicit move_into(void* storage) BOOST_NOEXCEPT
419         : storage_(storage)
420     {
421     }
422 
423 public: // internal visitor interface
424 
425     template <typename T>
426         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const427     internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
428     {
429         new(storage_) T( ::boost::detail::variant::move(operand.get()) );
430         BOOST_VARIANT_AUX_RETURN_VOID;
431     }
432 
433     template <typename T>
434         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(T & operand,int) const435     internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
436     {
437         new(storage_) T(::boost::detail::variant::move(operand));
438         BOOST_VARIANT_AUX_RETURN_VOID;
439     }
440 };
441 #endif
442 
443 ///////////////////////////////////////////////////////////////////////////////
444 // (detail) class assign_storage
445 //
446 // Internal visitor that assigns the given storage (which must be a
447 // constructed value of the same type) to the value it visits.
448 //
449 struct assign_storage
450     : public static_visitor<>
451 {
452 private: // representation
453 
454     const void* rhs_storage_;
455 
456 public: // structors
457 
assign_storageboost::detail::variant::assign_storage458     explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
459         : rhs_storage_(rhs_storage)
460     {
461     }
462 
463 public: // internal visitor interfaces
464 
465     template <typename T>
466         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::assign_storage467     internal_visit(backup_holder<T>& lhs_content, long) const
468     {
469         lhs_content.get()
470             = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
471         BOOST_VARIANT_AUX_RETURN_VOID;
472     }
473 
474     template <typename T>
475         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::assign_storage476     internal_visit(const backup_holder<T>& lhs_content, long) const
477     {
478         lhs_content.get()
479             = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
480         BOOST_VARIANT_AUX_RETURN_VOID;
481     }
482 
483     template <typename T>
484         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::assign_storage485     internal_visit(T& lhs_content, int) const
486     {
487         // NOTE TO USER :
488         // Compile error here indicates one of variant's bounded types does
489         // not meet the requirements of the Assignable concept. Thus,
490         // variant is not Assignable.
491         //
492         // Hint: Are any of the bounded types const-qualified or references?
493         //
494         lhs_content = *static_cast< const T* >(rhs_storage_);
495         BOOST_VARIANT_AUX_RETURN_VOID;
496     }
497 
498 };
499 
500 ///////////////////////////////////////////////////////////////////////////////
501 // (detail) class move_storage
502 //
503 // Internal visitor that moves the given storage (which must be a
504 // constructed value of the same type) to the value it visits.
505 //
506 struct move_storage
507     : public static_visitor<>
508 {
509 private: // representation
510 
511     void* rhs_storage_;
512 
513 public: // structors
514 
move_storageboost::detail::variant::move_storage515     explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
516         : rhs_storage_(rhs_storage)
517     {
518     }
519 
520 public: // internal visitor interfaces
521 
522     template <typename T>
523         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::move_storage524     internal_visit(backup_holder<T>& lhs_content, long) const
525     {
526         lhs_content.get()
527             = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
528         BOOST_VARIANT_AUX_RETURN_VOID;
529     }
530 
531     template <typename T>
532         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::move_storage533     internal_visit(const backup_holder<T>& lhs_content, long) const
534     {
535         lhs_content.get()
536             = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
537         BOOST_VARIANT_AUX_RETURN_VOID;
538     }
539 
540     template <typename T>
541         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::move_storage542     internal_visit(T& lhs_content, int) const
543     {
544         // NOTE TO USER :
545         // Compile error here indicates one of variant's bounded types does
546         // not meet the requirements of the Assignable concept. Thus,
547         // variant is not Assignable.
548         //
549         // Hint: Are any of the bounded types const-qualified or references?
550         //
551         lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
552         BOOST_VARIANT_AUX_RETURN_VOID;
553     }
554 
555 };
556 
557 ///////////////////////////////////////////////////////////////////////////////
558 // (detail) class direct_assigner
559 //
560 // Generic static visitor that: if and only if the visited value is of the
561 // specified type, assigns the given value to the visited value and returns
562 // true; else returns false.
563 //
564 template <typename T>
565 class direct_assigner
566     : public static_visitor<bool>
567 {
568 private: // representation
569 
570     const T& rhs_;
571 
572 public: // structors
573 
direct_assigner(const T & rhs)574     explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
575         : rhs_(rhs)
576     {
577     }
578 
579 public: // visitor interface
580 
operator ()(T & lhs)581     bool operator()(T& lhs)
582     {
583         lhs = rhs_;
584         return true;
585     }
586 
587     template <typename U>
operator ()(U &)588     bool operator()(U&) BOOST_NOEXCEPT
589     {
590         return false;
591     }
592 
593 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
594 private:
595     // silence MSVC warning C4512: assignment operator could not be generated
596     direct_assigner& operator= (direct_assigner const&);
597 #endif
598 };
599 
600 ///////////////////////////////////////////////////////////////////////////////
601 // (detail) class direct_mover
602 //
603 // Generic static visitor that: if and only if the visited value is of the
604 // specified type, move assigns the given value to the visited value and returns
605 // true; else returns false.
606 //
607 template <typename T>
608 class direct_mover
609     : public static_visitor<bool>
610 {
611 private: // representation
612 
613     T& rhs_;
614 
615 public: // structors
616 
direct_mover(T & rhs)617     explicit direct_mover(T& rhs) BOOST_NOEXCEPT
618         : rhs_(rhs)
619     {
620     }
621 
622 public: // visitor interface
623 
operator ()(T & lhs)624     bool operator()(T& lhs)
625     {
626         lhs = ::boost::detail::variant::move(rhs_);
627         return true;
628     }
629 
630     template <typename U>
operator ()(U &)631     bool operator()(U&) BOOST_NOEXCEPT
632     {
633         return false;
634     }
635 
636 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
637 private:
638     // silence MSVC warning C4512: assignment operator could not be generated
639     direct_mover& operator= (direct_mover const&);
640 #endif
641 };
642 
643 
644 ///////////////////////////////////////////////////////////////////////////////
645 // (detail) class backup_assigner
646 //
647 // Internal visitor that "assigns" the given value to the visited value,
648 // using backup to recover if the destroy-copy sequence fails.
649 //
650 // NOTE: This needs to be a friend of variant, as it needs access to
651 // indicate_which, indicate_backup_which, etc.
652 //
653 template <typename Variant>
654 class backup_assigner
655     : public static_visitor<>
656 {
657 private: // representation
658 
659     Variant& lhs_;
660     int rhs_which_;
661     const void* rhs_content_;
662     void (*copy_rhs_content_)(void*, const void*);
663 
664 public: // structors
665 
666     template<class RhsT>
backup_assigner(Variant & lhs,int rhs_which,const RhsT & rhs_content)667     backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
668         : lhs_(lhs)
669         , rhs_which_(rhs_which)
670         , rhs_content_(&rhs_content)
671         , copy_rhs_content_(&construct_impl<RhsT>)
672     {
673     }
674 
675 private: // helpers, for visitor interface (below)
676 
677     template<class RhsT>
construct_impl(void * addr,const void * obj)678     static void construct_impl(void* addr, const void* obj)
679     {
680         new(addr) RhsT(*static_cast<const RhsT*>(obj));
681     }
682 
683     template <typename LhsT>
backup_assign_impl(backup_holder<LhsT> & lhs_content,mpl::false_,long)684     void backup_assign_impl(
685           backup_holder<LhsT>& lhs_content
686         , mpl::false_ // is_nothrow_move_constructible
687         , long
688         )
689     {
690         // Move lhs content to backup...
691         backup_holder<LhsT> backup_lhs_content(0);
692         backup_lhs_content.swap(lhs_content); // nothrow
693 
694         // ...destroy lhs content...
695         lhs_content.~backup_holder<LhsT>(); // nothrow
696 
697         BOOST_TRY
698         {
699             // ...and attempt to copy rhs content into lhs storage:
700             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
701         }
702         BOOST_CATCH (...)
703         {
704             // In case of failure, copy backup pointer to lhs storage...
705             new(lhs_.storage_.address())
706                     backup_holder<LhsT>( 0 ); // nothrow
707 
708             static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
709                     ->swap(backup_lhs_content); // nothrow
710 
711             // ...and rethrow:
712             BOOST_RETHROW;
713         }
714         BOOST_CATCH_END
715 
716         // In case of success, indicate new content type:
717         lhs_.indicate_which(rhs_which_); // nothrow
718     }
719 
720     template <typename LhsT>
backup_assign_impl(LhsT & lhs_content,mpl::true_,int)721     void backup_assign_impl(
722           LhsT& lhs_content
723         , mpl::true_ // is_nothrow_move_constructible
724         , int
725         )
726     {
727         // Move lhs content to backup...
728         LhsT backup_lhs_content(
729               ::boost::detail::variant::move(lhs_content)
730             ); // nothrow
731 
732         // ...destroy lhs content...
733         lhs_content.~LhsT(); // nothrow
734 
735         BOOST_TRY
736         {
737             // ...and attempt to copy rhs content into lhs storage:
738             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
739         }
740         BOOST_CATCH (...)
741         {
742             // In case of failure, restore backup content to lhs storage...
743             new(lhs_.storage_.address())
744                 LhsT(
745                       ::boost::detail::variant::move(backup_lhs_content)
746                     ); // nothrow
747 
748             // ...and rethrow:
749             BOOST_RETHROW;
750         }
751         BOOST_CATCH_END
752 
753         // In case of success, indicate new content type:
754         lhs_.indicate_which(rhs_which_); // nothrow
755     }
756 
757     template <typename LhsT>
backup_assign_impl(LhsT & lhs_content,mpl::false_,int)758     void backup_assign_impl(
759           LhsT& lhs_content
760         , mpl::false_ // is_nothrow_move_constructible
761         , int
762         )
763     {
764         // Backup lhs content...
765         LhsT* backup_lhs_ptr = new LhsT(lhs_content);
766 
767         // ...destroy lhs content...
768         lhs_content.~LhsT(); // nothrow
769 
770         BOOST_TRY
771         {
772             // ...and attempt to copy rhs content into lhs storage:
773             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
774         }
775         BOOST_CATCH (...)
776         {
777             // In case of failure, copy backup pointer to lhs storage...
778             new(lhs_.storage_.address())
779                 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
780 
781             // ...indicate now using backup...
782             lhs_.indicate_backup_which( lhs_.which() ); // nothrow
783 
784             // ...and rethrow:
785             BOOST_RETHROW;
786         }
787         BOOST_CATCH_END
788 
789         // In case of success, indicate new content type...
790         lhs_.indicate_which(rhs_which_); // nothrow
791 
792         // ...and delete backup:
793         delete backup_lhs_ptr; // nothrow
794     }
795 
796 public: // visitor interface
797 
798     template <typename LhsT>
799         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(LhsT & lhs_content,int)800     internal_visit(LhsT& lhs_content, int)
801     {
802         typedef typename is_nothrow_move_constructible<LhsT>::type
803             nothrow_move;
804 
805         backup_assign_impl( lhs_content, nothrow_move(), 1L);
806 
807         BOOST_VARIANT_AUX_RETURN_VOID;
808     }
809 
810 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
811 private:
812     // silence MSVC warning C4512: assignment operator could not be generated
813     backup_assigner& operator= (backup_assigner const&);
814 #endif
815 };
816 
817 ///////////////////////////////////////////////////////////////////////////////
818 // (detail) class swap_with
819 //
820 // Visitor that swaps visited value with content of given variant.
821 //
822 // Precondition: Given variant MUST have same logical type as visited value.
823 //
824 template <typename Variant>
825 struct swap_with
826     : public static_visitor<>
827 {
828 private: // representation
829 
830     Variant& toswap_;
831 
832 public: // structors
833 
swap_withboost::detail::variant::swap_with834     explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
835         : toswap_(toswap)
836     {
837     }
838 
839 public: // internal visitor interfaces
840 
841     template <typename T>
operator ()boost::detail::variant::swap_with842     void operator()(T& operand) const
843     {
844         // Since the precondition ensures types are same, get T...
845         known_get<T> getter;
846         T& other = toswap_.apply_visitor(getter);
847 
848         // ...and swap:
849         ::boost::detail::variant::move_swap( operand, other );
850     }
851 
852 private:
853     swap_with& operator=(const swap_with&);
854 
855 };
856 
857 ///////////////////////////////////////////////////////////////////////////////
858 // (detail) class reflect
859 //
860 // Generic static visitor that performs a typeid on the value it visits.
861 //
862 
863 class reflect
864     : public static_visitor<const boost::typeindex::type_info&>
865 {
866 public: // visitor interfaces
867 
868     template <typename T>
operator ()(const T &) const869     const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
870     {
871         return boost::typeindex::type_id<T>().type_info();
872     }
873 
874 };
875 
876 ///////////////////////////////////////////////////////////////////////////////
877 // (detail) class comparer
878 //
879 // Generic static visitor that compares the content of the given lhs variant
880 // with the visited rhs content using Comp.
881 //
882 // Precondition: lhs.which() == rhs.which()
883 //
884 template <typename Variant, typename Comp>
885 class comparer
886     : public static_visitor<bool>
887 {
888 private: // representation
889 
890     const Variant& lhs_;
891 
892 public: // structors
893 
comparer(const Variant & lhs)894     explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
895         : lhs_(lhs)
896     {
897     }
898 
899 public: // visitor interfaces
900 
901     template <typename T>
operator ()(const T & rhs_content) const902     bool operator()(const T& rhs_content) const
903     {
904         // Since the precondition ensures lhs and rhs types are same, get T...
905         known_get<const T> getter;
906         const T& lhs_content = lhs_.apply_visitor(getter);
907 
908         // ...and compare lhs and rhs contents:
909         return Comp()(lhs_content, rhs_content);
910     }
911 
912 private:
913     comparer& operator=(const comparer&);
914 
915 };
916 
917 ///////////////////////////////////////////////////////////////////////////////
918 // (detail) class equal_comp
919 //
920 // Generic function object compares lhs with rhs using operator==.
921 //
922 struct equal_comp
923 {
924     template <typename T>
operator ()boost::detail::variant::equal_comp925     bool operator()(const T& lhs, const T& rhs) const
926     {
927         return lhs == rhs;
928     }
929 };
930 
931 ///////////////////////////////////////////////////////////////////////////////
932 // (detail) class less_comp
933 //
934 // Generic function object compares lhs with rhs using operator<.
935 //
936 struct less_comp
937 {
938     template <typename T>
operator ()boost::detail::variant::less_comp939     bool operator()(const T& lhs, const T& rhs) const
940     {
941         return lhs < rhs;
942     }
943 };
944 
945 ///////////////////////////////////////////////////////////////////////////////
946 // (detail) class template invoke_visitor
947 //
948 // Internal visitor that invokes the given visitor using:
949 //  * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
950 //  * for all other values, the value itself.
951 //
952 template <typename Visitor>
953 class invoke_visitor
954 {
955 private: // representation
956 
957     Visitor& visitor_;
958 
959 public: // visitor typedefs
960 
961     typedef typename Visitor::result_type
962         result_type;
963 
964 public: // structors
965 
invoke_visitor(Visitor & visitor)966     explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
967         : visitor_(visitor)
968     {
969     }
970 
971 #if !defined(BOOST_NO_VOID_RETURNS)
972 
973 public: // internal visitor interfaces
974 
975     template <typename T>
internal_visit(T & operand,int)976     result_type internal_visit(T& operand, int)
977     {
978         return visitor_(operand);
979     }
980 
981 #   if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
982     template <typename T>
internal_visit(const T & operand,int)983     result_type internal_visit(const T& operand, int)
984     {
985         return visitor_(operand);
986     }
987 #   endif
988 
989 #else // defined(BOOST_NO_VOID_RETURNS)
990 
991 private: // helpers, for internal visitor interfaces (below)
992 
993     template <typename T>
994         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
visit_impl(T & operand,mpl::false_)995     visit_impl(T& operand, mpl::false_)
996     {
997         return visitor_(operand);
998     }
999 
1000     template <typename T>
1001         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
visit_impl(T & operand,mpl::true_)1002     visit_impl(T& operand, mpl::true_)
1003     {
1004         visitor_(operand);
1005         BOOST_VARIANT_AUX_RETURN_VOID;
1006     }
1007 
1008 public: // internal visitor interfaces
1009 
1010     template <typename T>
1011         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(T & operand,int)1012     internal_visit(T& operand, int)
1013     {
1014         typedef typename is_same<result_type, void>::type
1015             has_void_result_type;
1016 
1017         return visit_impl(operand, has_void_result_type());
1018     }
1019 
1020 #endif // BOOST_NO_VOID_RETURNS) workaround
1021 
1022 public: // internal visitor interfaces, cont.
1023 
1024     template <typename T>
1025         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(boost::recursive_wrapper<T> & operand,long)1026     internal_visit(boost::recursive_wrapper<T>& operand, long)
1027     {
1028         return internal_visit( operand.get(), 1L );
1029     }
1030 
1031     template <typename T>
1032         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(const boost::recursive_wrapper<T> & operand,long)1033     internal_visit(const boost::recursive_wrapper<T>& operand, long)
1034     {
1035         return internal_visit( operand.get(), 1L );
1036     }
1037 
1038     template <typename T>
1039         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(boost::detail::reference_content<T> & operand,long)1040     internal_visit(boost::detail::reference_content<T>& operand, long)
1041     {
1042         return internal_visit( operand.get(), 1L );
1043     }
1044 
1045     template <typename T>
1046         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(const boost::detail::reference_content<T> & operand,long)1047     internal_visit(const boost::detail::reference_content<T>& operand, long)
1048     {
1049         return internal_visit( operand.get(), 1L );
1050     }
1051 
1052     template <typename T>
1053         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(boost::detail::variant::backup_holder<T> & operand,long)1054     internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1055     {
1056         return internal_visit( operand.get(), 1L );
1057     }
1058 
1059     template <typename T>
1060         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long)1061     internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1062     {
1063         return internal_visit( operand.get(), 1L );
1064     }
1065 
1066 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1067 private:
1068     // silence MSVC warning C4512: assignment operator could not be generated
1069     invoke_visitor& operator= (invoke_visitor const&);
1070 #endif
1071 };
1072 
1073 }} // namespace detail::variant
1074 
1075 ///////////////////////////////////////////////////////////////////////////////
1076 // class template variant (concept inspired by Andrei Alexandrescu)
1077 //
1078 // See docs and boost/variant/variant_fwd.hpp for more information.
1079 //
1080 template <
1081       typename T0_
1082     , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1083     >
1084 class variant
1085 {
1086 private: // helpers, for typedefs (below)
1087 
1088     typedef variant wknd_self_t;
1089 
1090     struct is_recursive_
1091         : detail::variant::is_recursive_flag<T0_>
1092     {
1093     };
1094 
1095     typedef typename mpl::eval_if<
1096           is_recursive_
1097         , T0_
1098         , mpl::identity< T0_ >
1099         >::type unwrapped_T0_;
1100 
1101     struct is_sequence_based_
1102         : detail::variant::is_over_sequence<unwrapped_T0_>
1103     {
1104     };
1105 
1106 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1107 
1108 private: // helpers, for typedefs (below)
1109 
1110     typedef typename mpl::eval_if<
1111           is_sequence_based_
1112         , unwrapped_T0_ // over_sequence<...>::type
1113         , detail::variant::make_variant_list<
1114               unwrapped_T0_
1115             , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1116             >
1117         >::type specified_types;
1118 
1119     BOOST_STATIC_ASSERT((
1120           ::boost::mpl::not_< mpl::empty<specified_types> >::value
1121         ));
1122 
1123     typedef typename mpl::eval_if<
1124           is_recursive_
1125         , mpl::transform<
1126               specified_types
1127             , mpl::protect<
1128                   detail::variant::quoted_enable_recursive<wknd_self_t>
1129                 >
1130             >
1131         , mpl::identity< specified_types >
1132         >::type recursive_enabled_types;
1133 
1134 public: // public typedefs
1135 
1136     typedef typename mpl::transform<
1137           recursive_enabled_types
1138         , unwrap_recursive<mpl::_1>
1139         >::type types;
1140 
1141 private: // internal typedefs
1142 
1143     typedef typename mpl::transform<
1144           recursive_enabled_types
1145         , mpl::protect< detail::make_reference_content<> >
1146         >::type internal_types;
1147 
1148     typedef typename mpl::front<
1149           internal_types
1150         >::type internal_T0;
1151 
1152 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1153 
1154 private: // helpers, for typedefs (below)
1155 
1156     typedef unwrapped_T0_ T0;
1157 
1158     #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1159         typedef typename mpl::eval_if< \
1160               is_recursive_ \
1161             , detail::variant::enable_recursive< \
1162                   BOOST_PP_CAT(T,N) \
1163                 , wknd_self_t \
1164                 > \
1165             , mpl::identity< BOOST_PP_CAT(T,N) > \
1166             >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1167         /**/
1168 
1169     BOOST_PP_REPEAT(
1170           BOOST_VARIANT_LIMIT_TYPES
1171         , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1172         , _
1173         )
1174 
1175     #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1176 
1177     #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1178         typedef typename unwrap_recursive< \
1179               BOOST_PP_CAT(recursive_enabled_T,N) \
1180             >::type BOOST_PP_CAT(public_T,N); \
1181         /**/
1182 
1183     BOOST_PP_REPEAT(
1184           BOOST_VARIANT_LIMIT_TYPES
1185         , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1186         , _
1187         )
1188 
1189     #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1190 
1191 public: // public typedefs
1192 
1193     typedef typename detail::variant::make_variant_list<
1194           BOOST_VARIANT_ENUM_PARAMS(public_T)
1195         >::type types;
1196 
1197 private: // helpers, for internal typedefs (below)
1198 
1199     #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1200         typedef detail::make_reference_content< \
1201               BOOST_PP_CAT(recursive_enabled_T,N) \
1202             >::type BOOST_PP_CAT(internal_T,N); \
1203         /**/
1204 
1205     BOOST_PP_REPEAT(
1206           BOOST_VARIANT_LIMIT_TYPES
1207         , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1208         , _
1209         )
1210 
1211     #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1212 
1213 private: // internal typedefs
1214 
1215     typedef typename detail::variant::make_variant_list<
1216           BOOST_VARIANT_ENUM_PARAMS(internal_T)
1217         >::type internal_types;
1218 
1219 private: // static precondition assertions
1220 
1221     // NOTE TO USER :
1222     // variant< type-sequence > syntax is not supported on this compiler!
1223     //
1224     BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1225 
1226 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1227 
1228 private: // helpers, for representation (below)
1229 
1230     typedef typename detail::variant::find_fallback_type<
1231           internal_types
1232         >::type fallback_type_result_;
1233 
1234     typedef typename fallback_type_result_::first
1235         fallback_type_index_;
1236     typedef typename fallback_type_result_::second
1237         fallback_type_;
1238 
1239     struct has_fallback_type_
1240         : mpl::not_<
1241               is_same< fallback_type_, detail::variant::no_fallback_type >
1242             >
1243     {
1244     };
1245 
1246     typedef has_fallback_type_
1247         never_uses_backup_flag;
1248 
1249     typedef typename detail::variant::make_storage<
1250           internal_types, never_uses_backup_flag
1251         >::type storage_t;
1252 
1253 #ifndef BOOST_NO_CXX11_NOEXCEPT
1254     typedef typename detail::variant::is_variant_move_noexcept_constructible<
1255         internal_types
1256     > variant_move_noexcept_constructible;
1257 
1258     typedef typename detail::variant::is_variant_move_noexcept_assignable<
1259         internal_types
1260     > variant_move_noexcept_assignable;
1261 
1262 #endif
1263 
1264 private: // helpers, for representation (below)
1265 
1266     // which_ on:
1267     // * [0,  size<internal_types>) indicates stack content
1268     // * [-size<internal_types>, 0) indicates pointer to heap backup
1269     // if which_ >= 0:
1270     // * then which() -> which_
1271     // * else which() -> -(which_ + 1)
1272 
1273 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1274 
1275     typedef int which_t;
1276 
1277 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1278 
1279     // [if O1_size available, then attempt which_t size optimization...]
1280     // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1281     typedef typename mpl::eval_if<
1282           mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1283         , mpl::identity< int >
1284         , mpl::if_<
1285               mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1286             , signed char
1287             , int
1288             >
1289         >::type which_t;
1290 
1291 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1292 
1293 // representation -- private when possible
1294 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1295     private:
1296 #else
1297     public:
1298 #endif
1299 
1300     which_t which_;
1301     storage_t storage_;
1302 
indicate_which(int which_arg)1303     void indicate_which(int which_arg) BOOST_NOEXCEPT
1304     {
1305         which_ = static_cast<which_t>( which_arg );
1306     }
1307 
indicate_backup_which(int which_arg)1308     void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1309     {
1310         which_ = static_cast<which_t>( -(which_arg + 1) );
1311     }
1312 
1313 private: // helpers, for queries (below)
1314 
using_backup() const1315     bool using_backup() const BOOST_NOEXCEPT
1316     {
1317         return which_ < 0;
1318     }
1319 
1320 public: // queries
1321 
which() const1322     int which() const BOOST_NOEXCEPT
1323     {
1324         // If using heap backup...
1325         if (using_backup())
1326             // ...then return adjusted which_:
1327             return -(which_ + 1);
1328 
1329         // Otherwise, return which_ directly:
1330         return which_;
1331     }
1332 
1333 private: // helpers, for structors (below)
1334 
1335     struct initializer
1336         : BOOST_VARIANT_AUX_INITIALIZER_T(
1337               recursive_enabled_types, recursive_enabled_T
1338             )
1339     {
1340     };
1341 
destroy_content()1342     void destroy_content() BOOST_NOEXCEPT
1343     {
1344         detail::variant::destroyer visitor;
1345         this->internal_apply_visitor(visitor);
1346     }
1347 
1348 public: // structors
1349 
~variant()1350     ~variant() BOOST_NOEXCEPT
1351     {
1352         destroy_content();
1353     }
1354 
BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)1355     variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1356     {
1357 #ifdef _MSC_VER
1358 #pragma warning( push )
1359 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1360 #pragma warning( disable : 4345 )
1361 #endif
1362         // NOTE TO USER :
1363         // Compile error from here indicates that the first bound
1364         // type is not default-constructible, and so variant cannot
1365         // support its own default-construction.
1366         //
1367         new( storage_.address() ) internal_T0();
1368         indicate_which(0); // zero is the index of the first bounded type
1369 #ifdef _MSC_VER
1370 #pragma warning( pop )
1371 #endif
1372     }
1373 
1374 private: // helpers, for structors, cont. (below)
1375 
1376     class convert_copy_into
1377         : public static_visitor<int>
1378     {
1379     private: // representation
1380 
1381         void* storage_;
1382 
1383     public: // structors
1384 
convert_copy_into(void * storage)1385         explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1386             : storage_(storage)
1387         {
1388         }
1389 
1390     public: // internal visitor interfaces (below)
1391 
1392         template <typename T>
internal_visit(T & operand,int) const1393         int internal_visit(T& operand, int) const
1394         {
1395             // NOTE TO USER :
1396             // Compile error here indicates one of the source variant's types
1397             // cannot be unambiguously converted to the destination variant's
1398             // types (or that no conversion exists).
1399             //
1400             return initializer::initialize(storage_, operand);
1401         }
1402 
1403 #   if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1404         template <typename T>
internal_visit(const T & operand,int) const1405         result_type internal_visit(const T& operand, int) const
1406         {
1407             return initializer::initialize(storage_, operand);
1408         }
1409 #   endif
1410 
1411         template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long) const1412         int internal_visit(boost::detail::reference_content<T>& operand, long) const
1413         {
1414             return internal_visit( operand.get(), 1L );
1415         }
1416 
1417         template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long) const1418         int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1419         {
1420             return internal_visit( operand.get(), 1L );
1421         }
1422 
1423         template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const1424         int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1425         {
1426             return internal_visit( operand.get(), 1L );
1427         }
1428 
1429         template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const1430         int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1431         {
1432             return internal_visit( operand.get(), 1L );
1433         }
1434 
1435         template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long) const1436         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1437         {
1438             return internal_visit( operand.get(), 1L );
1439         }
1440 
1441         template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long) const1442         int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1443         {
1444             return internal_visit( operand.get(), 1L );
1445         }
1446 
1447     };
1448 
1449     friend class convert_copy_into;
1450 
1451 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1452     class convert_move_into
1453         : public static_visitor<int>
1454     {
1455     private: // representation
1456 
1457         void* storage_;
1458 
1459     public: // structors
1460 
convert_move_into(void * storage)1461         explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1462             : storage_(storage)
1463         {
1464         }
1465 
1466     public: // internal visitor interfaces (below)
1467 
1468         template <typename T>
internal_visit(T & operand,int) const1469         int internal_visit(T& operand, int) const
1470         {
1471             // NOTE TO USER :
1472             // Compile error here indicates one of the source variant's types
1473             // cannot be unambiguously converted to the destination variant's
1474             // types (or that no conversion exists).
1475             //
1476             return initializer::initialize(storage_, detail::variant::move(operand) );
1477         }
1478 
1479         template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long) const1480         int internal_visit(boost::detail::reference_content<T>& operand, long) const
1481         {
1482             return internal_visit( operand.get(), 1L );
1483         }
1484 
1485         template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long) const1486         int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1487         {
1488             return internal_visit( operand.get(), 1L );
1489         }
1490 
1491         template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const1492         int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1493         {
1494             return internal_visit( operand.get(), 1L );
1495         }
1496 
1497         template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const1498         int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1499         {
1500             return internal_visit( operand.get(), 1L );
1501         }
1502 
1503         template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long) const1504         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1505         {
1506             return internal_visit( operand.get(), 1L );
1507         }
1508 
1509         template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long) const1510         int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1511         {
1512             return internal_visit( operand.get(), 1L );
1513         }
1514     };
1515 
1516     friend class convert_move_into;
1517 #endif
1518 
1519 private: // helpers, for structors, below
1520 
1521     template <typename T>
convert_construct(T & operand,int,mpl::false_=mpl::false_ ())1522     void convert_construct(
1523           T& operand
1524         , int
1525         , mpl::false_ = mpl::false_() // is_foreign_variant
1526         )
1527     {
1528         // NOTE TO USER :
1529         // Compile error here indicates that the given type is not
1530         // unambiguously convertible to one of the variant's types
1531         // (or that no conversion exists).
1532         //
1533         indicate_which(
1534               initializer::initialize(
1535                   storage_.address()
1536                 , operand
1537                 )
1538             );
1539     }
1540 
1541 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1542     template <typename T>
convert_construct(T && operand,int,mpl::false_=mpl::false_ ())1543     typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1544           T&& operand
1545         , int
1546         , mpl::false_ = mpl::false_() // is_foreign_variant
1547         )
1548     {
1549         // NOTE TO USER :
1550         // Compile error here indicates that the given type is not
1551         // unambiguously convertible to one of the variant's types
1552         // (or that no conversion exists).
1553         //
1554         indicate_which(
1555               initializer::initialize(
1556                   storage_.address()
1557                 , detail::variant::move(operand)
1558                 )
1559             );
1560     }
1561 #endif
1562 
1563     template <typename Variant>
convert_construct(Variant & operand,long,mpl::true_)1564     void convert_construct(
1565           Variant& operand
1566         , long
1567         , mpl::true_// is_foreign_variant
1568         )
1569     {
1570         convert_copy_into visitor(storage_.address());
1571         indicate_which(
1572               operand.internal_apply_visitor(visitor)
1573             );
1574     }
1575 
1576 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1577     template <typename Variant>
convert_construct(Variant && operand,long,mpl::true_)1578     typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1579           Variant&& operand
1580         , long
1581         , mpl::true_// is_foreign_variant
1582         )
1583     {
1584         convert_move_into visitor(storage_.address());
1585         indicate_which(
1586               operand.internal_apply_visitor(visitor)
1587             );
1588     }
1589 #endif
1590 
1591     template <typename Variant>
convert_construct_variant(Variant & operand)1592     void convert_construct_variant(Variant& operand)
1593     {
1594         // [Determine if the given variant is itself a bounded type, or if its
1595         //  content needs to be converted (i.e., it is a 'foreign' variant):]
1596         //
1597 
1598         typedef typename mpl::find_if<
1599               types
1600             , is_same<
1601                   add_const<mpl::_1>
1602                 , const Variant
1603                 >
1604             >::type found_it;
1605 
1606         typedef typename mpl::end<types>::type not_found;
1607         typedef typename is_same<
1608               found_it, not_found
1609             >::type is_foreign_variant;
1610 
1611         // Convert construct from operand:
1612         convert_construct(
1613               operand, 1L
1614             , is_foreign_variant()
1615             );
1616     }
1617 
1618 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1619     template <typename Variant>
convert_construct_variant(Variant && operand)1620     typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1621     {
1622         // [Determine if the given variant is itself a bounded type, or if its
1623         //  content needs to be converted (i.e., it is a 'foreign' variant):]
1624         //
1625 
1626         typedef typename mpl::find_if<
1627               types
1628             , is_same<
1629                   add_const<mpl::_1>
1630                 , const Variant
1631                 >
1632             >::type found_it;
1633 
1634         typedef typename mpl::end<types>::type not_found;
1635         typedef typename is_same<
1636               found_it, not_found
1637             >::type is_foreign_variant;
1638 
1639         // Convert move construct from operand:
1640         convert_construct(
1641               detail::variant::move(operand), 1L
1642             , is_foreign_variant()
1643             );
1644     }
1645 #endif
1646 
1647     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
convert_construct(boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> & operand,long)1648     void convert_construct(
1649           boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1650         , long
1651         )
1652     {
1653         convert_construct_variant(operand);
1654     }
1655 
1656     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
convert_construct(const boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> & operand,long)1657     void convert_construct(
1658           const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1659         , long
1660         )
1661     {
1662         convert_construct_variant(operand);
1663     }
1664 
1665 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1666     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
convert_construct(boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> && operand,long)1667     void convert_construct(
1668           boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1669         , long
1670         )
1671     {
1672         convert_construct_variant( detail::variant::move(operand) );
1673     }
1674 #endif
1675 
1676 public: // structors, cont.
1677 
1678 #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
1679 
1680     template <typename T>
variant(const T & operand)1681     variant(const T& operand)
1682     {
1683         convert_construct(operand, 1L);
1684     }
1685 
1686     template <typename T>
variant(T & operand)1687     variant(T& operand)
1688     {
1689         convert_construct(operand, 1L);
1690     }
1691 
1692 #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1693 
1694     // For compilers that cannot distinguish between T& and const T& in
1695     // template constructors, but do fully support SFINAE, we can workaround:
1696 
1697     template <typename T>
1698     variant(const T& operand)
1699     {
1700         convert_construct(operand, 1L);
1701     }
1702 
1703     template <typename T>
1704     variant(
1705           T& operand
1706         , typename enable_if<
1707               mpl::not_< is_const<T> >
1708             , void
1709             >::type* = 0
1710         )
1711     {
1712         convert_construct(operand, 1L);
1713     }
1714 
1715 #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1716 
1717     // For compilers that cannot distinguish between T& and const T& in
1718     // template constructors, and do NOT support SFINAE, we can't workaround:
1719 
1720     template <typename T>
1721     variant(const T& operand)
1722     {
1723         convert_construct(operand, 1L);
1724     }
1725 #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
1726 
1727 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1728     template <class T>
variant(T && operand,typename boost::enable_if<boost::is_rvalue_reference<T &&>>::type * =0,typename boost::disable_if<boost::is_const<T>>::type * =0)1729     variant(T&& operand, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0,
1730         typename boost::disable_if<boost::is_const<T> >::type* = 0)
1731     {
1732         convert_construct( detail::variant::move(operand), 1L);
1733     }
1734 #endif
1735 
1736 public: // structors, cont.
1737 
1738     // [MSVC6 requires copy constructor appear after template constructors]
variant(const variant & operand)1739     variant(const variant& operand)
1740     {
1741         // Copy the value of operand into *this...
1742         detail::variant::copy_into visitor( storage_.address() );
1743         operand.internal_apply_visitor(visitor);
1744 
1745         // ...and activate the *this's primary storage on success:
1746         indicate_which(operand.which());
1747     }
1748 
1749 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)1750     variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1751     {
1752         // Move the value of operand into *this...
1753         detail::variant::move_into visitor( storage_.address() );
1754         operand.internal_apply_visitor(visitor);
1755 
1756         // ...and activate the *this's primary storage on success:
1757         indicate_which(operand.which());
1758     }
1759 #endif
1760 
1761 private: // helpers, for modifiers (below)
1762 
1763 #   if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1764     template <typename Variant>
1765     friend class detail::variant::backup_assigner;
1766 #   endif
1767 
1768     // class assigner
1769     //
1770     // Internal visitor that "assigns" the visited value to the given variant
1771     // by appropriate destruction and copy-construction.
1772     //
1773 
1774     class assigner
1775         : public static_visitor<>
1776     {
1777     protected: // representation
1778 
1779         variant& lhs_;
1780         const int rhs_which_;
1781 
1782     public: // structors
1783 
assigner(variant & lhs,int rhs_which)1784         assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1785             : lhs_(lhs)
1786             , rhs_which_(rhs_which)
1787         {
1788         }
1789 
1790     protected: // helpers, for internal visitor interface (below)
1791 
1792         template <typename RhsT, typename B1, typename B2>
assign_impl(const RhsT & rhs_content,mpl::true_,B1,B2) const1793         void assign_impl(
1794               const RhsT& rhs_content
1795             , mpl::true_ // has_nothrow_copy
1796             , B1 // is_nothrow_move_constructible
1797             , B2 // has_fallback_type
1798             ) const BOOST_NOEXCEPT
1799         {
1800             // Destroy lhs's content...
1801             lhs_.destroy_content(); // nothrow
1802 
1803             // ...copy rhs content into lhs's storage...
1804             new(lhs_.storage_.address())
1805                 RhsT( rhs_content ); // nothrow
1806 
1807             // ...and indicate new content type:
1808             lhs_.indicate_which(rhs_which_); // nothrow
1809         }
1810 
1811         template <typename RhsT, typename B>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::true_,B) const1812         void assign_impl(
1813               const RhsT& rhs_content
1814             , mpl::false_ // has_nothrow_copy
1815             , mpl::true_ // is_nothrow_move_constructible
1816             , B // has_fallback_type
1817             ) const
1818         {
1819             // Attempt to make a temporary copy (so as to move it below)...
1820             RhsT temp(rhs_content);
1821 
1822             // ...and upon success destroy lhs's content...
1823             lhs_.destroy_content(); // nothrow
1824 
1825             // ...move the temporary copy into lhs's storage...
1826             new(lhs_.storage_.address())
1827                 RhsT( detail::variant::move(temp) ); // nothrow
1828 
1829             // ...and indicate new content type:
1830             lhs_.indicate_which(rhs_which_); // nothrow
1831         }
1832 
construct_fallback() const1833         void construct_fallback() const BOOST_NOEXCEPT {
1834             // In case of failure, default-construct fallback type in lhs's storage...
1835             new (lhs_.storage_.address())
1836                 fallback_type_; // nothrow
1837 
1838             // ...indicate construction of fallback type...
1839             lhs_.indicate_which(
1840                   BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1841                 ); // nothrow
1842         }
1843 
1844         template <typename RhsT>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::false_,mpl::true_) const1845         void assign_impl(
1846               const RhsT& rhs_content
1847             , mpl::false_ // has_nothrow_copy
1848             , mpl::false_ // is_nothrow_move_constructible
1849             , mpl::true_ // has_fallback_type
1850             ) const
1851         {
1852             // Destroy lhs's content...
1853             lhs_.destroy_content(); // nothrow
1854 
1855             BOOST_TRY
1856             {
1857                 // ...and attempt to copy rhs's content into lhs's storage:
1858                 new(lhs_.storage_.address())
1859                     RhsT( rhs_content );
1860             }
1861             BOOST_CATCH (...)
1862             {
1863                 construct_fallback();
1864 
1865                 // ...and rethrow:
1866                 BOOST_RETHROW;
1867             }
1868             BOOST_CATCH_END
1869 
1870             // In the event of success, indicate new content type:
1871             lhs_.indicate_which(rhs_which_); // nothrow
1872         }
1873 
1874         template <typename RhsT>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::false_,mpl::false_) const1875         void assign_impl(
1876               const RhsT& rhs_content
1877             , mpl::false_ // has_nothrow_copy
1878             , mpl::false_ // is_nothrow_move_constructible
1879             , mpl::false_ // has_fallback_type
1880             ) const
1881         {
1882             detail::variant::backup_assigner<wknd_self_t>
1883                 visitor(lhs_, rhs_which_, rhs_content);
1884             lhs_.internal_apply_visitor(visitor);
1885         }
1886 
1887     public: // internal visitor interfaces
1888 
1889         template <typename RhsT>
1890             BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(const RhsT & rhs_content,int) const1891         internal_visit(const RhsT& rhs_content, int) const
1892         {
1893             typedef typename has_nothrow_copy<RhsT>::type
1894                 nothrow_copy;
1895             typedef typename mpl::or_< // reduces compile-time
1896                   nothrow_copy
1897                 , is_nothrow_move_constructible<RhsT>
1898                 >::type nothrow_move_constructor;
1899 
1900             assign_impl(
1901                   rhs_content
1902                 , nothrow_copy()
1903                 , nothrow_move_constructor()
1904                 , has_fallback_type_()
1905                 );
1906 
1907             BOOST_VARIANT_AUX_RETURN_VOID;
1908         }
1909 
1910 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1911     private:
1912         // silence MSVC warning C4512: assignment operator could not be generated
1913         assigner& operator= (assigner const&);
1914 #endif
1915     };
1916 
1917     friend class assigner;
1918 
1919 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1920     // class move_assigner
1921     //
1922     // Internal visitor that "move assigns" the visited value to the given variant
1923     // by appropriate destruction and move-construction.
1924     //
1925 
1926     class move_assigner
1927         : public assigner
1928     {
1929     public: // structors
1930 
move_assigner(variant & lhs,int rhs_which)1931         move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1932             : assigner(lhs, rhs_which)
1933         {
1934         }
1935 
1936     private: // helpers, for internal visitor interface (below)
1937 
1938         template <typename RhsT, typename B2>
assign_impl(RhsT & rhs_content,mpl::true_,mpl::false_,B2) const1939         void assign_impl(
1940               RhsT& rhs_content
1941             , mpl::true_ // has_nothrow_copy
1942             , mpl::false_ // is_nothrow_move_constructible
1943             , B2 // has_fallback_type
1944             ) const BOOST_NOEXCEPT
1945         {
1946             assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
1947         }
1948 
1949         template <typename RhsT, typename B, typename B2>
assign_impl(RhsT & rhs_content,B,mpl::true_,B2) const1950         void assign_impl(
1951               RhsT& rhs_content
1952             , B // has_nothrow_copy
1953             , mpl::true_ // is_nothrow_move_constructible
1954             , B2 // has_fallback_type
1955             ) const BOOST_NOEXCEPT
1956         {
1957             // ...destroy lhs's content...
1958             assigner::lhs_.destroy_content(); // nothrow
1959 
1960             // ...move the rhs_content into lhs's storage...
1961             new(assigner::lhs_.storage_.address())
1962                 RhsT( detail::variant::move(rhs_content) ); // nothrow
1963 
1964             // ...and indicate new content type:
1965             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1966         }
1967 
1968         template <typename RhsT>
assign_impl(RhsT & rhs_content,mpl::false_,mpl::false_,mpl::true_) const1969         void assign_impl(
1970               RhsT& rhs_content
1971             , mpl::false_ // has_nothrow_copy
1972             , mpl::false_ // is_nothrow_move_constructible
1973             , mpl::true_ // has_fallback_type
1974             ) const
1975         {
1976             // Destroy lhs's content...
1977             assigner::lhs_.destroy_content(); // nothrow
1978 
1979             BOOST_TRY
1980             {
1981                 // ...and attempt to copy rhs's content into lhs's storage:
1982                 new(assigner::lhs_.storage_.address())
1983                     RhsT( detail::variant::move(rhs_content) );
1984             }
1985             BOOST_CATCH (...)
1986             {
1987                 assigner::construct_fallback();
1988 
1989                 // ...and rethrow:
1990                 BOOST_RETHROW;
1991             }
1992             BOOST_CATCH_END
1993 
1994             // In the event of success, indicate new content type:
1995             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1996         }
1997 
1998         template <typename RhsT>
assign_impl(RhsT & rhs_content,mpl::false_,mpl::false_,mpl::false_) const1999         void assign_impl(
2000               RhsT& rhs_content
2001             , mpl::false_ // has_nothrow_copy
2002             , mpl::false_ // is_nothrow_move_constructible
2003             , mpl::false_ // has_fallback_type
2004             ) const
2005         {
2006             assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2007         }
2008 
2009     public: // internal visitor interfaces
2010 
2011         template <typename RhsT>
2012             BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(RhsT & rhs_content,int) const2013         internal_visit(RhsT& rhs_content, int) const
2014         {
2015             typedef typename is_nothrow_move_constructible<RhsT>::type
2016                 nothrow_move_constructor;
2017             typedef typename mpl::or_< // reduces compile-time
2018                   nothrow_move_constructor
2019                 , has_nothrow_copy<RhsT>
2020                 >::type nothrow_copy;
2021 
2022             assign_impl(
2023                   rhs_content
2024                 , nothrow_copy()
2025                 , nothrow_move_constructor()
2026                 , has_fallback_type_()
2027                 );
2028 
2029             BOOST_VARIANT_AUX_RETURN_VOID;
2030         }
2031 
2032 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2033     private:
2034         // silence MSVC warning C4512: assignment operator could not be generated
2035         move_assigner& operator= (move_assigner const&);
2036 #endif
2037     };
2038 
2039     friend class move_assigner;
2040 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2041 
variant_assign(const variant & rhs)2042     void variant_assign(const variant& rhs)
2043     {
2044         // If the contained types are EXACTLY the same...
2045         if (which_ == rhs.which_)
2046         {
2047             // ...then assign rhs's storage to lhs's content:
2048             detail::variant::assign_storage visitor(rhs.storage_.address());
2049             this->internal_apply_visitor(visitor);
2050         }
2051         else
2052         {
2053             // Otherwise, perform general (copy-based) variant assignment:
2054             assigner visitor(*this, rhs.which());
2055             rhs.internal_apply_visitor(visitor);
2056         }
2057     }
2058 
2059 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
variant_assign(variant && rhs)2060     void variant_assign(variant&& rhs)
2061     {
2062         // If the contained types are EXACTLY the same...
2063         if (which_ == rhs.which_)
2064         {
2065             // ...then move rhs's storage to lhs's content:
2066             detail::variant::move_storage visitor(rhs.storage_.address());
2067             this->internal_apply_visitor(visitor);
2068         }
2069         else
2070         {
2071             // Otherwise, perform general (move-based) variant assignment:
2072             move_assigner visitor(*this, rhs.which());
2073             rhs.internal_apply_visitor(visitor);
2074         }
2075     }
2076 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2077 
2078 private: // helpers, for modifiers (below)
2079 
2080     template <typename T>
assign(const T & rhs)2081     void assign(const T& rhs)
2082     {
2083         // If direct T-to-T assignment is not possible...
2084         detail::variant::direct_assigner<T> direct_assign(rhs);
2085         if (this->apply_visitor(direct_assign) == false)
2086         {
2087             // ...then convert rhs to variant and assign:
2088             //
2089             // While potentially inefficient, the following construction of a
2090             // variant allows T as any type convertible to one of the bounded
2091             // types without excessive code redundancy.
2092             //
2093             variant temp(rhs);
2094             variant_assign( detail::variant::move(temp) );
2095         }
2096     }
2097 
2098 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2099     template <typename T>
move_assign(T && rhs)2100     void move_assign(T&& rhs)
2101     {
2102         // If direct T-to-T move assignment is not possible...
2103         detail::variant::direct_mover<T> direct_move(rhs);
2104         if (this->apply_visitor(direct_move) == false)
2105         {
2106             // ...then convert rhs to variant and assign:
2107             //
2108             // While potentially inefficient, the following construction of a
2109             // variant allows T as any type convertible to one of the bounded
2110             // types without excessive code redundancy.
2111             //
2112             variant temp( detail::variant::move(rhs) );
2113             variant_assign( detail::variant::move(temp) );
2114         }
2115     }
2116 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2117 
2118 public: // modifiers
2119 
2120 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2121     template <class T>
2122     typename boost::enable_if_c<boost::is_rvalue_reference<T&&>::value && !boost::is_const<T>::value, variant& >::type
operator =(T && rhs)2123         operator=(T&& rhs)
2124     {
2125         move_assign( detail::variant::move(rhs) );
2126         return *this;
2127     }
2128 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2129 
2130     template <typename T>
operator =(const T & rhs)2131     variant& operator=(const T& rhs)
2132     {
2133         assign(rhs);
2134         return *this;
2135     }
2136 
2137     // [MSVC6 requires copy assign appear after templated operator=]
operator =(const variant & rhs)2138     variant& operator=(const variant& rhs)
2139     {
2140         variant_assign(rhs);
2141         return *this;
2142     }
2143 
2144 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =(variant && rhs)2145     variant& operator=(variant&& rhs)
2146 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6)
2147         BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2148 #endif
2149     {
2150         variant_assign( detail::variant::move(rhs) );
2151         return *this;
2152     }
2153 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2154 
swap(variant & rhs)2155     void swap(variant& rhs)
2156     {
2157         // If the contained types are the same...
2158         if (which() == rhs.which())
2159         {
2160             // ...then swap the values directly:
2161             detail::variant::swap_with<variant> visitor(rhs);
2162             this->apply_visitor(visitor);
2163         }
2164         else
2165         {
2166             // ...otherwise, perform general variant swap:
2167             variant tmp( detail::variant::move(rhs) );
2168             rhs = detail::variant::move(*this);
2169             *this = detail::variant::move(tmp);
2170         }
2171     }
2172 
2173 public: // queries
2174 
2175     //
2176     // NOTE: member which() defined above.
2177     //
2178 
empty() const2179     bool empty() const BOOST_NOEXCEPT
2180     {
2181         return false;
2182     }
2183 
type() const2184     const boost::typeindex::type_info& type() const
2185     {
2186         detail::variant::reflect visitor;
2187         return this->apply_visitor(visitor);
2188     }
2189 
2190 public: // prevent comparison with foreign types
2191 
2192 // Obsolete. Remove.
2193 #   define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
2194     void
2195 
2196     template <typename U>
operator ==(const U &) const2197     void operator==(const U&) const
2198     {
2199         BOOST_STATIC_ASSERT( false && sizeof(U) );
2200     }
2201 
2202     template <typename U>
operator <(const U &) const2203     void operator<(const U&) const
2204     {
2205         BOOST_STATIC_ASSERT( false && sizeof(U) );
2206     }
2207 
2208     template <typename U>
operator !=(const U &) const2209     void operator!=(const U&) const
2210     {
2211         BOOST_STATIC_ASSERT( false && sizeof(U) );
2212     }
2213 
2214     template <typename U>
operator >(const U &) const2215     void operator>(const U&) const
2216     {
2217         BOOST_STATIC_ASSERT( false && sizeof(U) );
2218     }
2219 
2220     template <typename U>
operator <=(const U &) const2221     void operator<=(const U&) const
2222     {
2223         BOOST_STATIC_ASSERT( false && sizeof(U) );
2224     }
2225 
2226     template <typename U>
operator >=(const U &) const2227     void operator>=(const U&) const
2228     {
2229         BOOST_STATIC_ASSERT( false && sizeof(U) );
2230     }
2231 
2232 public: // comparison operators
2233 
2234     // [MSVC6 requires these operators appear after template operators]
2235 
operator ==(const variant & rhs) const2236     bool operator==(const variant& rhs) const
2237     {
2238         if (this->which() != rhs.which())
2239             return false;
2240 
2241         detail::variant::comparer<
2242               variant, detail::variant::equal_comp
2243             > visitor(*this);
2244         return rhs.apply_visitor(visitor);
2245     }
2246 
operator <(const variant & rhs) const2247     bool operator<(const variant& rhs) const
2248     {
2249         //
2250         // Dirk Schreib suggested this collating order.
2251         //
2252 
2253         if (this->which() != rhs.which())
2254             return this->which() < rhs.which();
2255 
2256         detail::variant::comparer<
2257               variant, detail::variant::less_comp
2258             > visitor(*this);
2259         return rhs.apply_visitor(visitor);
2260     }
2261 
2262     ///////////////////////////////////////////////////////////////////////////////
2263     // comparison operators != > <= >=
operator !=(const variant & rhs) const2264     inline bool operator!=(const variant& rhs) const
2265     {
2266         return !(*this == rhs);
2267     }
2268 
operator >(const variant & rhs) const2269     inline bool operator>(const variant& rhs) const
2270     {
2271         return rhs < *this;
2272     }
2273 
operator <=(const variant & rhs) const2274     inline bool operator<=(const variant& rhs) const
2275     {
2276         return !(*this > rhs);
2277     }
2278 
operator >=(const variant & rhs) const2279     inline bool operator>=(const variant& rhs) const
2280     {
2281         return !(*this < rhs);
2282     }
2283 
2284 // helpers, for visitation support (below) -- private when possible
2285 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2286 
2287     template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2288     friend class variant;
2289 
2290 private:
2291 
2292 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2293 
2294 public:
2295 
2296 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2297 
2298     template <typename Visitor, typename VoidPtrCV>
2299     static
2300         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2301               typename Visitor::result_type
2302             )
internal_apply_visitor_impl(int internal_which,int logical_which,Visitor & visitor,VoidPtrCV storage)2303     internal_apply_visitor_impl(
2304           int internal_which
2305         , int logical_which
2306         , Visitor& visitor
2307         , VoidPtrCV storage
2308         )
2309     {
2310         typedef mpl::int_<0> first_which;
2311         typedef typename mpl::begin<internal_types>::type first_it;
2312         typedef typename mpl::end<internal_types>::type last_it;
2313 
2314         typedef detail::variant::visitation_impl_step<
2315               first_it, last_it
2316             > first_step;
2317 
2318         return detail::variant::visitation_impl(
2319               internal_which, logical_which
2320             , visitor, storage, mpl::false_()
2321             , never_uses_backup_flag()
2322             , static_cast<first_which*>(0), static_cast<first_step*>(0)
2323             );
2324     }
2325 
2326     template <typename Visitor>
2327         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2328               typename Visitor::result_type
2329             )
internal_apply_visitor(Visitor & visitor)2330     internal_apply_visitor(Visitor& visitor)
2331     {
2332         return internal_apply_visitor_impl(
2333               which_, which(), visitor, storage_.address()
2334             );
2335     }
2336 
2337     template <typename Visitor>
2338         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2339               typename Visitor::result_type
2340             )
internal_apply_visitor(Visitor & visitor) const2341     internal_apply_visitor(Visitor& visitor) const
2342     {
2343         return internal_apply_visitor_impl(
2344               which_, which(), visitor, storage_.address()
2345             );
2346     }
2347 
2348 public: // visitation support
2349 
2350     template <typename Visitor>
2351         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2352               typename Visitor::result_type
2353             )
apply_visitor(Visitor & visitor)2354     apply_visitor(Visitor& visitor)
2355     {
2356         detail::variant::invoke_visitor<Visitor> invoker(visitor);
2357         return this->internal_apply_visitor(invoker);
2358     }
2359 
2360     template <typename Visitor>
2361         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2362               typename Visitor::result_type
2363             )
apply_visitor(Visitor & visitor) const2364     apply_visitor(Visitor& visitor) const
2365     {
2366         detail::variant::invoke_visitor<Visitor> invoker(visitor);
2367         return this->internal_apply_visitor(invoker);
2368     }
2369 
2370 }; // class variant
2371 
2372 ///////////////////////////////////////////////////////////////////////////////
2373 // metafunction make_variant_over
2374 //
2375 // See docs and boost/variant/variant_fwd.hpp for more information.
2376 //
2377 template <typename Types>
2378 struct make_variant_over
2379 {
2380 private: // precondition assertions
2381 
2382     BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2383 
2384 public: // metafunction result
2385 
2386     typedef variant<
2387           detail::variant::over_sequence< Types >
2388         > type;
2389 
2390 };
2391 
2392 
2393 ///////////////////////////////////////////////////////////////////////////////
2394 // function template swap
2395 //
2396 // Swaps two variants of the same type (i.e., identical specification).
2397 //
2398 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
swap(variant<BOOST_VARIANT_ENUM_PARAMS (T)> & lhs,variant<BOOST_VARIANT_ENUM_PARAMS (T)> & rhs)2399 inline void swap(
2400       variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2401     , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2402     )
2403 {
2404     lhs.swap(rhs);
2405 }
2406 
2407 } // namespace boost
2408 
2409 // implementation additions
2410 
2411 #if !defined(BOOST_NO_IOSTREAM)
2412 #include "boost/variant/detail/variant_io.hpp"
2413 #endif // BOOST_NO_IOSTREAM
2414 
2415 #endif // BOOST_VARIANT_VARIANT_HPP
2416