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