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