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