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