• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
2 #define BOOST_VARIANT2_VARIANT_HPP_INCLUDED
3 
4 // Copyright 2017-2019 Peter Dimov.
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 //
8 // See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt
10 
11 #if defined(_MSC_VER) && _MSC_VER < 1910
12 # pragma warning( push )
13 # pragma warning( disable: 4521 4522 ) // multiple copy operators
14 #endif
15 
16 #ifndef BOOST_MP11_HPP_INCLUDED
17 #include <boost/mp11.hpp>
18 #endif
19 #include <boost/config.hpp>
20 #include <boost/detail/workaround.hpp>
21 #include <boost/cstdint.hpp>
22 #include <cstddef>
23 #include <type_traits>
24 #include <exception>
25 #include <cassert>
26 #include <initializer_list>
27 #include <utility>
28 #include <functional> // std::hash
29 
30 //
31 
32 namespace boost
33 {
34 
35 #ifdef BOOST_NO_EXCEPTIONS
36 
37 BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
38 
39 #endif
40 
41 namespace variant2
42 {
43 
44 // bad_variant_access
45 
46 class bad_variant_access: public std::exception
47 {
48 public:
49 
bad_variant_access()50     bad_variant_access() noexcept
51     {
52     }
53 
what() const54     char const * what() const noexcept
55     {
56         return "bad_variant_access";
57     }
58 };
59 
60 namespace detail
61 {
62 
throw_bad_variant_access()63 BOOST_NORETURN inline void throw_bad_variant_access()
64 {
65 #ifdef BOOST_NO_EXCEPTIONS
66 
67     boost::throw_exception( bad_variant_access() );
68 
69 #else
70 
71     throw bad_variant_access();
72 
73 #endif
74 }
75 
76 } // namespace detail
77 
78 // monostate
79 
80 struct monostate
81 {
82 };
83 
operator <(monostate,monostate)84 constexpr bool operator<(monostate, monostate) noexcept { return false; }
operator >(monostate,monostate)85 constexpr bool operator>(monostate, monostate) noexcept { return false; }
operator <=(monostate,monostate)86 constexpr bool operator<=(monostate, monostate) noexcept { return true; }
operator >=(monostate,monostate)87 constexpr bool operator>=(monostate, monostate) noexcept { return true; }
operator ==(monostate,monostate)88 constexpr bool operator==(monostate, monostate) noexcept { return true; }
operator !=(monostate,monostate)89 constexpr bool operator!=(monostate, monostate) noexcept { return false; }
90 
91 // variant forward declaration
92 
93 template<class... T> class variant;
94 
95 // variant_size
96 
97 template<class T> struct variant_size
98 {
99 };
100 
101 template<class T> struct variant_size<T const>: variant_size<T>
102 {
103 };
104 
105 template<class T> struct variant_size<T volatile>: variant_size<T>
106 {
107 };
108 
109 template<class T> struct variant_size<T const volatile>: variant_size<T>
110 {
111 };
112 
113 template<class T> struct variant_size<T&>: variant_size<T>
114 {
115 };
116 
117 template<class T> struct variant_size<T&&>: variant_size<T>
118 {
119 };
120 
121 #if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
122 
123 template <class T> /*inline*/ constexpr std::size_t variant_size_v = variant_size<T>::value;
124 
125 #endif
126 
127 template <class... T> struct variant_size<variant<T...>>: mp11::mp_size<variant<T...>>
128 {
129 };
130 
131 // variant_alternative
132 
133 template<std::size_t I, class T> struct variant_alternative;
134 
135 template<std::size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type;
136 
137 #if BOOST_WORKAROUND(BOOST_GCC, < 40900)
138 
139 namespace detail
140 {
141 
142 template<std::size_t I, class T, bool E> struct variant_alternative_impl
143 {
144 };
145 
146 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>, true>
147 {
148     using type = mp11::mp_at_c<variant<T...>, I>;
149 };
150 
151 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const, true>: std::add_const< mp11::mp_at_c<variant<T...>, I> >
152 {
153 };
154 
155 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile, true>: std::add_volatile< mp11::mp_at_c<variant<T...>, I> >
156 {
157 };
158 
159 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile, true>: std::add_cv< mp11::mp_at_c<variant<T...>, I> >
160 {
161 };
162 
163 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> >
164 {
165 };
166 
167 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> const >
168 {
169 };
170 
171 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> volatile >
172 {
173 };
174 
175 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> const volatile >
176 {
177 };
178 
179 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> >
180 {
181 };
182 
183 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> const >
184 {
185 };
186 
187 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> volatile >
188 {
189 };
190 
191 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> const volatile >
192 {
193 };
194 
195 } // namespace detail
196 
197 template<std::size_t I, class T> struct variant_alternative
198 {
199 };
200 
201 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: public detail::variant_alternative_impl<I, variant<T...>, (I < sizeof...(T))>
202 {
203 };
204 
205 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const>: public detail::variant_alternative_impl<I, variant<T...> const, (I < sizeof...(T))>
206 {
207 };
208 
209 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile>: public detail::variant_alternative_impl<I, variant<T...> volatile, (I < sizeof...(T))>
210 {
211 };
212 
213 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile>: public detail::variant_alternative_impl<I, variant<T...> const volatile, (I < sizeof...(T))>
214 {
215 };
216 
217 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&>: public detail::variant_alternative_impl<I, variant<T...>&, (I < sizeof...(T))>
218 {
219 };
220 
221 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const&>: public detail::variant_alternative_impl<I, variant<T...> const&, (I < sizeof...(T))>
222 {
223 };
224 
225 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile&>: public detail::variant_alternative_impl<I, variant<T...> volatile&, (I < sizeof...(T))>
226 {
227 };
228 
229 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile&>: public detail::variant_alternative_impl<I, variant<T...> const volatile&, (I < sizeof...(T))>
230 {
231 };
232 
233 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&&>: public detail::variant_alternative_impl<I, variant<T...>&&, (I < sizeof...(T))>
234 {
235 };
236 
237 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const&&>: public detail::variant_alternative_impl<I, variant<T...> const&&, (I < sizeof...(T))>
238 {
239 };
240 
241 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile&&>: public detail::variant_alternative_impl<I, variant<T...> volatile&&, (I < sizeof...(T))>
242 {
243 };
244 
245 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile&&>: public detail::variant_alternative_impl<I, variant<T...> const volatile&&, (I < sizeof...(T))>
246 {
247 };
248 
249 #else
250 
251 namespace detail
252 {
253 
254 #if defined( BOOST_MP11_VERSION ) && BOOST_MP11_VERSION >= 107000
255 
256 template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke_q<Q, variant_alternative_t<I::value, T>>;
257 
258 #else
259 
260 template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke<Q, variant_alternative_t<I::value, T>>;
261 
262 #endif
263 
264 } // namespace detail
265 
266 template<std::size_t I, class T> struct variant_alternative
267 {
268 };
269 
270 template<std::size_t I, class T> struct variant_alternative<I, T const>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_const>>
271 {
272 };
273 
274 template<std::size_t I, class T> struct variant_alternative<I, T volatile>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_volatile>>
275 {
276 };
277 
278 template<std::size_t I, class T> struct variant_alternative<I, T const volatile>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_cv>>
279 {
280 };
281 
282 template<std::size_t I, class T> struct variant_alternative<I, T&>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_lvalue_reference>>
283 {
284 };
285 
286 template<std::size_t I, class T> struct variant_alternative<I, T&&>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_rvalue_reference>>
287 {
288 };
289 
290 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: mp11::mp_defer<mp11::mp_at, variant<T...>, mp11::mp_size_t<I>>
291 {
292 };
293 
294 #endif
295 
296 // variant_npos
297 
298 constexpr std::size_t variant_npos = ~static_cast<std::size_t>( 0 );
299 
300 // holds_alternative
301 
holds_alternative(variant<T...> const & v)302 template<class U, class... T> constexpr bool holds_alternative( variant<T...> const& v ) noexcept
303 {
304     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
305     return v.index() == mp11::mp_find<variant<T...>, U>::value;
306 }
307 
308 // get (index)
309 
get(variant<T...> & v)310 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& get(variant<T...>& v)
311 {
312     static_assert( I < sizeof...(T), "Index out of bounds" );
313     return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
314 }
315 
get(variant<T...> && v)316 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& get(variant<T...>&& v)
317 {
318     static_assert( I < sizeof...(T), "Index out of bounds" );
319 
320 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
321 
322     return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
323 
324 #else
325 
326     if( v.index() != I ) detail::throw_bad_variant_access();
327     return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
328 
329 #endif
330 }
331 
get(variant<T...> const & v)332 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& get(variant<T...> const& v)
333 {
334     static_assert( I < sizeof...(T), "Index out of bounds" );
335     return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
336 }
337 
get(variant<T...> const && v)338 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& get(variant<T...> const&& v)
339 {
340     static_assert( I < sizeof...(T), "Index out of bounds" );
341 
342 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
343 
344     return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
345 
346 #else
347 
348     if( v.index() != I ) detail::throw_bad_variant_access();
349     return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
350 
351 #endif
352 }
353 
354 // detail::unsafe_get (for visit)
355 
356 namespace detail
357 {
358 
unsafe_get(variant<T...> & v)359 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& unsafe_get(variant<T...>& v)
360 {
361     static_assert( I < sizeof...(T), "Index out of bounds" );
362     return v._get_impl( mp11::mp_size_t<I>() );
363 }
364 
unsafe_get(variant<T...> && v)365 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& unsafe_get(variant<T...>&& v)
366 {
367     static_assert( I < sizeof...(T), "Index out of bounds" );
368     return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
369 }
370 
unsafe_get(variant<T...> const & v)371 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& unsafe_get(variant<T...> const& v)
372 {
373     static_assert( I < sizeof...(T), "Index out of bounds" );
374     return v._get_impl( mp11::mp_size_t<I>() );
375 }
376 
unsafe_get(variant<T...> const && v)377 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& unsafe_get(variant<T...> const&& v)
378 {
379     static_assert( I < sizeof...(T), "Index out of bounds" );
380     return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
381 }
382 
383 } // namespace detail
384 
385 // get (type)
386 
get(variant<T...> & v)387 template<class U, class... T> constexpr U& get(variant<T...>& v)
388 {
389     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
390 
391     using I = mp11::mp_find<variant<T...>, U>;
392 
393     return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
394 }
395 
get(variant<T...> && v)396 template<class U, class... T> constexpr U&& get(variant<T...>&& v)
397 {
398     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
399 
400     using I = mp11::mp_find<variant<T...>, U>;
401 
402 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
403 
404     return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
405 
406 #else
407 
408     if( v.index() != I::value ) detail::throw_bad_variant_access();
409     return std::move( v._get_impl( I() ) );
410 
411 #endif
412 }
413 
get(variant<T...> const & v)414 template<class U, class... T> constexpr U const& get(variant<T...> const& v)
415 {
416     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
417 
418     using I = mp11::mp_find<variant<T...>, U>;
419 
420     return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
421 }
422 
get(variant<T...> const && v)423 template<class U, class... T> constexpr U const&& get(variant<T...> const&& v)
424 {
425     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
426 
427     using I = mp11::mp_find<variant<T...>, U>;
428 
429 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
430 
431     return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
432 
433 #else
434 
435     if( v.index() != I::value ) detail::throw_bad_variant_access();
436     return std::move( v._get_impl( I() ) );
437 
438 #endif
439 }
440 
441 // get_if
442 
get_if(variant<T...> * v)443 template<std::size_t I, class... T> constexpr typename std::add_pointer<variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...>* v) noexcept
444 {
445     static_assert( I < sizeof...(T), "Index out of bounds" );
446     return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
447 }
448 
get_if(variant<T...> const * v)449 template<std::size_t I, class... T> constexpr typename std::add_pointer<const variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...> const * v) noexcept
450 {
451     static_assert( I < sizeof...(T), "Index out of bounds" );
452     return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
453 }
454 
get_if(variant<T...> * v)455 template<class U, class... T> constexpr typename std::add_pointer<U>::type get_if(variant<T...>* v) noexcept
456 {
457     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
458 
459     using I = mp11::mp_find<variant<T...>, U>;
460 
461     return v && v->index() == I::value? &v->_get_impl( I() ): 0;
462 }
463 
get_if(variant<T...> const * v)464 template<class U, class... T> constexpr typename std::add_pointer<U const>::type get_if(variant<T...> const * v) noexcept
465 {
466     static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
467 
468     using I = mp11::mp_find<variant<T...>, U>;
469 
470     return v && v->index() == I::value? &v->_get_impl( I() ): 0;
471 }
472 
473 //
474 
475 namespace detail
476 {
477 
478 // trivially_*
479 
480 #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
481 
482 template<class T> struct is_trivially_copy_constructible: mp11::mp_bool<std::is_copy_constructible<T>::value && std::has_trivial_copy_constructor<T>::value>
483 {
484 };
485 
486 template<class T> struct is_trivially_copy_assignable: mp11::mp_bool<std::is_copy_assignable<T>::value && std::has_trivial_copy_assign<T>::value>
487 {
488 };
489 
490 template<class T> struct is_trivially_move_constructible: mp11::mp_bool<std::is_move_constructible<T>::value && std::is_trivial<T>::value>
491 {
492 };
493 
494 template<class T> struct is_trivially_move_assignable: mp11::mp_bool<std::is_move_assignable<T>::value && std::is_trivial<T>::value>
495 {
496 };
497 
498 #else
499 
500 using std::is_trivially_copy_constructible;
501 using std::is_trivially_copy_assignable;
502 using std::is_trivially_move_constructible;
503 using std::is_trivially_move_assignable;
504 
505 #endif
506 
507 // variant_storage
508 
509 template<class D, class... T> union variant_storage_impl;
510 
511 template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<std::is_trivially_destructible<T>...>, T...>;
512 
513 template<class D> union variant_storage_impl<D>
514 {
515 };
516 
517 // not all trivially destructible
518 template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T...>
519 {
520     T1 first_;
521     variant_storage<T...> rest_;
522 
variant_storage_impl(mp11::mp_size_t<0>,A &&...a)523     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
524     {
525     }
526 
variant_storage_impl(mp11::mp_size_t<I>,A &&...a)527     template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
528     {
529     }
530 
~variant_storage_impl()531     ~variant_storage_impl()
532     {
533     }
534 
emplace(mp11::mp_size_t<0>,A &&...a)535     template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a )
536     {
537         ::new( &first_ ) T1( std::forward<A>(a)... );
538     }
539 
emplace(mp11::mp_size_t<I>,A &&...a)540     template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
541     {
542         rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
543     }
544 
get(mp11::mp_size_t<0>)545     BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
get(mp11::mp_size_t<0>) const546     constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
547 
get(mp11::mp_size_t<I>)548     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-1>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
get(mp11::mp_size_t<I>) const549     template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
550 };
551 
552 template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> union variant_storage_impl<mp11::mp_false, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>
553 {
554     T0 t0_;
555     T1 t1_;
556     T2 t2_;
557     T3 t3_;
558     T4 t4_;
559     T5 t5_;
560     T6 t6_;
561     T7 t7_;
562     T8 t8_;
563     T9 t9_;
564 
565     variant_storage<T...> rest_;
566 
variant_storage_impl(mp11::mp_size_t<0>,A &&...a)567     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<1>,A &&...a)568     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<2>,A &&...a)569     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<3>,A &&...a)570     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<4>,A &&...a)571     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<5>,A &&...a)572     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<6>,A &&...a)573     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<7>,A &&...a)574     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<8>,A &&...a)575     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<9>,A &&...a)576     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
577 
variant_storage_impl(mp11::mp_size_t<I>,A &&...a)578     template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
579 
~variant_storage_impl()580     ~variant_storage_impl()
581     {
582     }
583 
emplace(mp11::mp_size_t<0>,A &&...a)584     template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<1>,A &&...a)585     template<class... A> void emplace( mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<2>,A &&...a)586     template<class... A> void emplace( mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<3>,A &&...a)587     template<class... A> void emplace( mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<4>,A &&...a)588     template<class... A> void emplace( mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<5>,A &&...a)589     template<class... A> void emplace( mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<6>,A &&...a)590     template<class... A> void emplace( mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<7>,A &&...a)591     template<class... A> void emplace( mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<8>,A &&...a)592     template<class... A> void emplace( mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
emplace(mp11::mp_size_t<9>,A &&...a)593     template<class... A> void emplace( mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
594 
emplace(mp11::mp_size_t<I>,A &&...a)595     template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
596     {
597         rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
598     }
599 
get(mp11::mp_size_t<0>)600     BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
get(mp11::mp_size_t<0>) const601     constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
602 
get(mp11::mp_size_t<1>)603     BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
get(mp11::mp_size_t<1>) const604     constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
605 
get(mp11::mp_size_t<2>)606     BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
get(mp11::mp_size_t<2>) const607     constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
608 
get(mp11::mp_size_t<3>)609     BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
get(mp11::mp_size_t<3>) const610     constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
611 
get(mp11::mp_size_t<4>)612     BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
get(mp11::mp_size_t<4>) const613     constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
614 
get(mp11::mp_size_t<5>)615     BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
get(mp11::mp_size_t<5>) const616     constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
617 
get(mp11::mp_size_t<6>)618     BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
get(mp11::mp_size_t<6>) const619     constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
620 
get(mp11::mp_size_t<7>)621     BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
get(mp11::mp_size_t<7>) const622     constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
623 
get(mp11::mp_size_t<8>)624     BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
get(mp11::mp_size_t<8>) const625     constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
626 
get(mp11::mp_size_t<9>)627     BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
get(mp11::mp_size_t<9>) const628     constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
629 
get(mp11::mp_size_t<I>)630     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-10>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
get(mp11::mp_size_t<I>) const631     template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-10> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
632 };
633 
634 // all trivially destructible
635 template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T...>
636 {
637     T1 first_;
638     variant_storage<T...> rest_;
639 
variant_storage_impl(mp11::mp_size_t<0>,A &&...a)640     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
641     {
642     }
643 
variant_storage_impl(mp11::mp_size_t<I>,A &&...a)644     template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
645     {
646     }
647 
emplace_impl(mp11::mp_false,mp11::mp_size_t<0>,A &&...a)648     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a )
649     {
650         ::new( &first_ ) T1( std::forward<A>(a)... );
651     }
652 
emplace_impl(mp11::mp_false,mp11::mp_size_t<I>,A &&...a)653     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
654     {
655         rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
656     }
657 
emplace_impl(mp11::mp_true,mp11::mp_size_t<I>,A &&...a)658     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
659     {
660         *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
661     }
662 
emplace(mp11::mp_size_t<I>,A &&...a)663     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
664     {
665         this->emplace_impl( mp11::mp_all<detail::is_trivially_move_assignable<T1>, detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
666     }
667 
get(mp11::mp_size_t<0>)668     BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
get(mp11::mp_size_t<0>) const669     constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
670 
get(mp11::mp_size_t<I>)671     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-1>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
get(mp11::mp_size_t<I>) const672     template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
673 };
674 
675 template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> union variant_storage_impl<mp11::mp_true, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>
676 {
677     T0 t0_;
678     T1 t1_;
679     T2 t2_;
680     T3 t3_;
681     T4 t4_;
682     T5 t5_;
683     T6 t6_;
684     T7 t7_;
685     T8 t8_;
686     T9 t9_;
687 
688     variant_storage<T...> rest_;
689 
variant_storage_impl(mp11::mp_size_t<0>,A &&...a)690     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<1>,A &&...a)691     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<2>,A &&...a)692     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<3>,A &&...a)693     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<4>,A &&...a)694     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<5>,A &&...a)695     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<6>,A &&...a)696     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<7>,A &&...a)697     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<8>,A &&...a)698     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
variant_storage_impl(mp11::mp_size_t<9>,A &&...a)699     template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
700 
variant_storage_impl(mp11::mp_size_t<I>,A &&...a)701     template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
702 
emplace_impl(mp11::mp_false,mp11::mp_size_t<0>,A &&...a)703     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<1>,A &&...a)704     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<2>,A &&...a)705     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<3>,A &&...a)706     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<4>,A &&...a)707     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<5>,A &&...a)708     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<6>,A &&...a)709     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<7>,A &&...a)710     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<8>,A &&...a)711     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
emplace_impl(mp11::mp_false,mp11::mp_size_t<9>,A &&...a)712     template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
713 
emplace_impl(mp11::mp_false,mp11::mp_size_t<I>,A &&...a)714     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
715     {
716         rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
717     }
718 
emplace_impl(mp11::mp_true,mp11::mp_size_t<I>,A &&...a)719     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
720     {
721         *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
722     }
723 
emplace(mp11::mp_size_t<I>,A &&...a)724     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
725     {
726         this->emplace_impl( mp11::mp_all<
727             detail::is_trivially_move_assignable<T0>,
728             detail::is_trivially_move_assignable<T1>,
729             detail::is_trivially_move_assignable<T2>,
730             detail::is_trivially_move_assignable<T3>,
731             detail::is_trivially_move_assignable<T4>,
732             detail::is_trivially_move_assignable<T5>,
733             detail::is_trivially_move_assignable<T6>,
734             detail::is_trivially_move_assignable<T7>,
735             detail::is_trivially_move_assignable<T8>,
736             detail::is_trivially_move_assignable<T9>,
737             detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
738     }
739 
get(mp11::mp_size_t<0>)740     BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
get(mp11::mp_size_t<0>) const741     constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
742 
get(mp11::mp_size_t<1>)743     BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
get(mp11::mp_size_t<1>) const744     constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
745 
get(mp11::mp_size_t<2>)746     BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
get(mp11::mp_size_t<2>) const747     constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
748 
get(mp11::mp_size_t<3>)749     BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
get(mp11::mp_size_t<3>) const750     constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
751 
get(mp11::mp_size_t<4>)752     BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
get(mp11::mp_size_t<4>) const753     constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
754 
get(mp11::mp_size_t<5>)755     BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
get(mp11::mp_size_t<5>) const756     constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
757 
get(mp11::mp_size_t<6>)758     BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
get(mp11::mp_size_t<6>) const759     constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
760 
get(mp11::mp_size_t<7>)761     BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
get(mp11::mp_size_t<7>) const762     constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
763 
get(mp11::mp_size_t<8>)764     BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
get(mp11::mp_size_t<8>) const765     constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
766 
get(mp11::mp_size_t<9>)767     BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
get(mp11::mp_size_t<9>) const768     constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
769 
get(mp11::mp_size_t<I>)770     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-10>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
get(mp11::mp_size_t<I>) const771     template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-10> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
772 };
773 
774 // resolve_overload_*
775 
776 template<class... T> struct overload;
777 
778 template<> struct overload<>
779 {
780     void operator()() const;
781 };
782 
783 template<class T1, class... T> struct overload<T1, T...>: overload<T...>
784 {
785     using overload<T...>::operator();
786     mp11::mp_identity<T1> operator()(T1) const;
787 };
788 
789 #if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
790 
791 template<class U, class... T> using resolve_overload_type_ = decltype( overload<T...>()(std::declval<U>()) );
792 
793 template<class U, class... T> struct resolve_overload_type_impl: mp11::mp_defer< resolve_overload_type_, U, T... >
794 {
795 };
796 
797 template<class U, class... T> using resolve_overload_type = typename resolve_overload_type_impl<U, T...>::type::type;
798 
799 #else
800 
801 template<class U, class... T> using resolve_overload_type = typename decltype( overload<T...>()(std::declval<U>()) )::type;
802 
803 #endif
804 
805 template<class U, class... T> using resolve_overload_index = mp11::mp_find<mp11::mp_list<T...>, resolve_overload_type<U, T...>>;
806 
807 // variant_base
808 
809 template<bool is_trivially_destructible, bool is_single_buffered, class... T> struct variant_base_impl;
810 template<class... T> using variant_base = variant_base_impl<mp11::mp_all<std::is_trivially_destructible<T>...>::value, mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value, T...>;
811 
812 struct none {};
813 
814 // trivially destructible, single buffered
815 template<class... T> struct variant_base_impl<true, true, T...>
816 {
817     int ix_;
818     variant_storage<none, T...> st1_;
819 
variant_base_implboost::variant2::detail::variant_base_impl820     constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
821     {
822     }
823 
variant_base_implboost::variant2::detail::variant_base_impl824     template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
825     {
826     }
827 
828     // requires: ix_ == 0
_replaceboost::variant2::detail::variant_base_impl829     template<class I, class... A> void _replace( I, A&&... a )
830     {
831         ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
832         ix_ = I::value + 1;
833     }
834 
indexboost::variant2::detail::variant_base_impl835     constexpr std::size_t index() const noexcept
836     {
837         return ix_ - 1;
838     }
839 
_get_implboost::variant2::detail::variant_base_impl840     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
841     {
842         size_t const J = I+1;
843 
844         assert( ix_ == J );
845 
846         return st1_.get( mp11::mp_size_t<J>() );
847     }
848 
_get_implboost::variant2::detail::variant_base_impl849     template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
850     {
851         // size_t const J = I+1;
852         // assert( ix_ == I+1 );
853 
854         return st1_.get( mp11::mp_size_t<I+1>() );
855     }
856 
emplace_implboost::variant2::detail::variant_base_impl857     template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, A&&... a )
858     {
859         static_assert( std::is_nothrow_constructible<U, A&&...>::value, "Logic error: U must be nothrow constructible from A&&..." );
860 
861         st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
862         ix_ = J;
863     }
864 
emplace_implboost::variant2::detail::variant_base_impl865     template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, A&&... a )
866     {
867         static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
868 
869         U tmp( std::forward<A>(a)... );
870 
871         st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
872         ix_ = J;
873     }
874 
emplaceboost::variant2::detail::variant_base_impl875     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
876     {
877         std::size_t const J = I+1;
878         using U = mp11::mp_at_c<variant<T...>, I>;
879 
880         this->emplace_impl<J, U>( std::is_nothrow_constructible<U, A&&...>(), std::forward<A>(a)... );
881     }
882 };
883 
884 // trivially destructible, double buffered
885 template<class... T> struct variant_base_impl<true, false, T...>
886 {
887     int ix_;
888     variant_storage<none, T...> st1_;
889     variant_storage<none, T...> st2_;
890 
variant_base_implboost::variant2::detail::variant_base_impl891     constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
892     {
893     }
894 
variant_base_implboost::variant2::detail::variant_base_impl895     template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
896     {
897     }
898 
899     // requires: ix_ == 0
_replaceboost::variant2::detail::variant_base_impl900     template<class I, class... A> void _replace( I, A&&... a )
901     {
902         ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
903         ix_ = I::value + 1;
904     }
905 
indexboost::variant2::detail::variant_base_impl906     constexpr std::size_t index() const noexcept
907     {
908         return ix_ >= 0? ix_ - 1: -ix_ - 1;
909     }
910 
_get_implboost::variant2::detail::variant_base_impl911     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
912     {
913         size_t const J = I+1;
914 
915         assert( ix_ == J || -ix_ == J );
916 
917         constexpr mp11::mp_size_t<J> j{};
918         return ix_ >= 0? st1_.get( j ): st2_.get( j );
919     }
920 
_get_implboost::variant2::detail::variant_base_impl921     template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
922     {
923         // size_t const J = I+1;
924         // assert( ix_ == J || -ix_ == J );
925         // constexpr mp_size_t<J> j{};
926 
927         return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
928     }
929 
emplaceboost::variant2::detail::variant_base_impl930     template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
931     {
932         size_t const J = I+1;
933 
934         if( ix_ >= 0 )
935         {
936             st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
937             ix_ = -static_cast<int>( J );
938         }
939         else
940         {
941             st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
942             ix_ = J;
943         }
944     }
945 };
946 
947 // not trivially destructible, single buffered
948 template<class... T> struct variant_base_impl<false, true, T...>
949 {
950     int ix_;
951     variant_storage<none, T...> st1_;
952 
variant_base_implboost::variant2::detail::variant_base_impl953     constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
954     {
955     }
956 
variant_base_implboost::variant2::detail::variant_base_impl957     template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
958     {
959     }
960 
961     // requires: ix_ == 0
_replaceboost::variant2::detail::variant_base_impl962     template<class I, class... A> void _replace( I, A&&... a )
963     {
964         ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
965         ix_ = I::value + 1;
966     }
967 
968     //[&]( auto I ){
969     //    using U = mp_at_c<mp_list<none, T...>, I>;
970     //    st1_.get( I ).~U();
971     //}
972 
973     struct _destroy_L1
974     {
975         variant_base_impl * this_;
976 
operator ()boost::variant2::detail::variant_base_impl::_destroy_L1977         template<class I> void operator()( I ) const noexcept
978         {
979             using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
980             this_->st1_.get( I() ).~U();
981         }
982     };
983 
_destroyboost::variant2::detail::variant_base_impl984     void _destroy() noexcept
985     {
986         if( ix_ > 0 )
987         {
988             mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
989         }
990     }
991 
~variant_base_implboost::variant2::detail::variant_base_impl992     ~variant_base_impl() noexcept
993     {
994         _destroy();
995     }
996 
indexboost::variant2::detail::variant_base_impl997     constexpr std::size_t index() const noexcept
998     {
999         return ix_ - 1;
1000     }
1001 
_get_implboost::variant2::detail::variant_base_impl1002     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
1003     {
1004         size_t const J = I+1;
1005 
1006         assert( ix_ == J );
1007 
1008         return st1_.get( mp11::mp_size_t<J>() );
1009     }
1010 
_get_implboost::variant2::detail::variant_base_impl1011     template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
1012     {
1013         // size_t const J = I+1;
1014         // assert( ix_ == J );
1015 
1016         return st1_.get( mp11::mp_size_t<I+1>() );
1017     }
1018 
emplaceboost::variant2::detail::variant_base_impl1019     template<std::size_t I, class... A> void emplace( A&&... a )
1020     {
1021         size_t const J = I+1;
1022 
1023         using U = mp11::mp_at_c<variant<T...>, I>;
1024 
1025         static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
1026 
1027         U tmp( std::forward<A>(a)... );
1028 
1029         _destroy();
1030 
1031         st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
1032         ix_ = J;
1033     }
1034 };
1035 
1036 // not trivially destructible, double buffered
1037 template<class... T> struct variant_base_impl<false, false, T...>
1038 {
1039     int ix_;
1040     variant_storage<none, T...> st1_;
1041     variant_storage<none, T...> st2_;
1042 
variant_base_implboost::variant2::detail::variant_base_impl1043     constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
1044     {
1045     }
1046 
variant_base_implboost::variant2::detail::variant_base_impl1047     template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
1048     {
1049     }
1050 
1051     // requires: ix_ == 0
_replaceboost::variant2::detail::variant_base_impl1052     template<class I, class... A> void _replace( I, A&&... a )
1053     {
1054         ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
1055         ix_ = I::value + 1;
1056     }
1057 
1058     //[&]( auto I ){
1059     //    using U = mp_at_c<mp_list<none, T...>, I>;
1060     //    st1_.get( I ).~U();
1061     //}
1062 
1063     struct _destroy_L1
1064     {
1065         variant_base_impl * this_;
1066 
operator ()boost::variant2::detail::variant_base_impl::_destroy_L11067         template<class I> void operator()( I ) const noexcept
1068         {
1069             using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
1070             this_->st1_.get( I() ).~U();
1071         }
1072     };
1073 
1074     struct _destroy_L2
1075     {
1076         variant_base_impl * this_;
1077 
operator ()boost::variant2::detail::variant_base_impl::_destroy_L21078         template<class I> void operator()( I ) const noexcept
1079         {
1080             using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
1081             this_->st2_.get( I() ).~U();
1082         }
1083     };
1084 
_destroyboost::variant2::detail::variant_base_impl1085     void _destroy() noexcept
1086     {
1087         if( ix_ > 0 )
1088         {
1089             mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
1090         }
1091         else if( ix_ < 0 )
1092         {
1093             mp11::mp_with_index<1 + sizeof...(T)>( -ix_, _destroy_L2{ this } );
1094         }
1095     }
1096 
~variant_base_implboost::variant2::detail::variant_base_impl1097     ~variant_base_impl() noexcept
1098     {
1099         _destroy();
1100     }
1101 
indexboost::variant2::detail::variant_base_impl1102     constexpr std::size_t index() const noexcept
1103     {
1104         return ix_ >= 0? ix_ - 1: -ix_ - 1;
1105     }
1106 
_get_implboost::variant2::detail::variant_base_impl1107     template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
1108     {
1109         size_t const J = I+1;
1110 
1111         assert( ix_ == J || -ix_ == J );
1112 
1113         constexpr mp11::mp_size_t<J> j{};
1114         return ix_ >= 0? st1_.get( j ): st2_.get( j );
1115     }
1116 
_get_implboost::variant2::detail::variant_base_impl1117     template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
1118     {
1119         // size_t const J = I+1;
1120         // assert( ix_ == J || -ix_ == J );
1121         // constexpr mp_size_t<J> j{};
1122 
1123         return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
1124     }
1125 
emplaceboost::variant2::detail::variant_base_impl1126     template<std::size_t I, class... A> void emplace( A&&... a )
1127     {
1128         size_t const J = I+1;
1129 
1130         if( ix_ >= 0 )
1131         {
1132             st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
1133             _destroy();
1134 
1135             ix_ = -static_cast<int>( J );
1136         }
1137         else
1138         {
1139             st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
1140             _destroy();
1141 
1142             ix_ = J;
1143         }
1144     }
1145 };
1146 
1147 } // namespace detail
1148 
1149 // in_place_type_t
1150 
1151 template<class T> struct in_place_type_t
1152 {
1153 };
1154 
1155 #if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
1156 
1157 template<class T> constexpr in_place_type_t<T> in_place_type{};
1158 
1159 #endif
1160 
1161 namespace detail
1162 {
1163 
1164 template<class T> struct is_in_place_type: std::false_type {};
1165 template<class T> struct is_in_place_type<in_place_type_t<T>>: std::true_type {};
1166 
1167 } // namespace detail
1168 
1169 // in_place_index_t
1170 
1171 template<std::size_t I> struct in_place_index_t
1172 {
1173 };
1174 
1175 #if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
1176 
1177 template<std::size_t I> constexpr in_place_index_t<I> in_place_index{};
1178 
1179 #endif
1180 
1181 namespace detail
1182 {
1183 
1184 template<class T> struct is_in_place_index: std::false_type {};
1185 template<std::size_t I> struct is_in_place_index<in_place_index_t<I>>: std::true_type {};
1186 
1187 } // namespace detail
1188 
1189 // is_nothrow_swappable
1190 
1191 namespace detail
1192 {
1193 
1194 namespace det2
1195 {
1196 
1197 using std::swap;
1198 
1199 template<class T> using is_swappable_impl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
1200 
1201 #if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
1202 
1203 template<class T> struct is_nothrow_swappable_impl_
1204 {
1205     static constexpr bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));
1206 };
1207 
1208 template<class T> using is_nothrow_swappable_impl = mp11::mp_bool< is_nothrow_swappable_impl_<T>::value >;
1209 
1210 #else
1211 
1212 template<class T> using is_nothrow_swappable_impl = typename std::enable_if<noexcept(swap(std::declval<T&>(), std::declval<T&>()))>::type;
1213 
1214 #endif
1215 
1216 } // namespace det2
1217 
1218 template<class T> struct is_swappable: mp11::mp_valid<det2::is_swappable_impl, T>
1219 {
1220 };
1221 
1222 #if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
1223 
1224 template<class T> struct is_nothrow_swappable: mp11::mp_eval_if<mp11::mp_not<is_swappable<T>>, mp11::mp_false, det2::is_nothrow_swappable_impl, T>
1225 {
1226 };
1227 
1228 #else
1229 
1230 template<class T> struct is_nothrow_swappable: mp11::mp_valid<det2::is_nothrow_swappable_impl, T>
1231 {
1232 };
1233 
1234 #endif
1235 
1236 // variant_cc_base
1237 
1238 template<bool CopyConstructible, bool TriviallyCopyConstructible, class... T> struct variant_cc_base_impl;
1239 
1240 template<class... T> using variant_cc_base = variant_cc_base_impl<
1241     mp11::mp_all<std::is_copy_constructible<T>...>::value,
1242     mp11::mp_all<detail::is_trivially_copy_constructible<T>...>::value,
1243     T...>;
1244 
1245 template<class... T> struct variant_cc_base_impl<true, true, T...>: public variant_base<T...>
1246 {
1247     using variant_base = detail::variant_base<T...>;
1248     using variant_base::variant_base;
1249 
1250     variant_cc_base_impl() = default;
1251     variant_cc_base_impl( variant_cc_base_impl const& ) = default;
1252     variant_cc_base_impl( variant_cc_base_impl && ) = default;
1253     variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
1254     variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1255 };
1256 
1257 template<bool B, class... T> struct variant_cc_base_impl<false, B, T...>: public variant_base<T...>
1258 {
1259     using variant_base = detail::variant_base<T...>;
1260     using variant_base::variant_base;
1261 
1262     variant_cc_base_impl() = default;
1263     variant_cc_base_impl( variant_cc_base_impl const& ) = delete;
1264     variant_cc_base_impl( variant_cc_base_impl && ) = default;
1265     variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
1266     variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1267 };
1268 
1269 template<class... T> struct variant_cc_base_impl<true, false, T...>: public variant_base<T...>
1270 {
1271     using variant_base = detail::variant_base<T...>;
1272     using variant_base::variant_base;
1273 
1274 public:
1275 
1276     // constructors
1277 
1278     variant_cc_base_impl() = default;
1279 
1280     // copy constructor
1281 
1282 private:
1283 
1284     struct L1
1285     {
1286         variant_base * this_;
1287         variant_base const & r;
1288 
operator ()boost::variant2::detail::variant_cc_base_impl::L11289         template<class I> void operator()( I i ) const
1290         {
1291             this_->_replace( i, r._get_impl( i ) );
1292         }
1293     };
1294 
1295 public:
1296 
variant_cc_base_implboost::variant2::detail::variant_cc_base_impl1297     variant_cc_base_impl( variant_cc_base_impl const& r )
1298         noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
1299         : variant_base()
1300     {
1301         mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
1302     }
1303 
1304     // move constructor
1305 
1306     variant_cc_base_impl( variant_cc_base_impl && ) = default;
1307 
1308     // assignment
1309 
1310     variant_cc_base_impl& operator=( variant_cc_base_impl const & ) = default;
1311     variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1312 };
1313 
1314 // variant_ca_base
1315 
1316 template<bool CopyAssignable, bool TriviallyCopyAssignable, class... T> struct variant_ca_base_impl;
1317 
1318 template<class... T> using variant_ca_base = variant_ca_base_impl<
1319     mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>::value,
1320     mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>::value,
1321     T...>;
1322 
1323 template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
1324 {
1325     using variant_base = detail::variant_cc_base<T...>;
1326     using variant_base::variant_base;
1327 
1328     variant_ca_base_impl() = default;
1329     variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1330     variant_ca_base_impl( variant_ca_base_impl && ) = default;
1331     variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = default;
1332     variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1333 };
1334 
1335 template<bool B, class... T> struct variant_ca_base_impl<false, B, T...>: public variant_cc_base<T...>
1336 {
1337     using variant_base = detail::variant_cc_base<T...>;
1338     using variant_base::variant_base;
1339 
1340     variant_ca_base_impl() = default;
1341     variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1342     variant_ca_base_impl( variant_ca_base_impl && ) = default;
1343     variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = delete;
1344     variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1345 };
1346 
1347 template<class... T> struct variant_ca_base_impl<true, false, T...>: public variant_cc_base<T...>
1348 {
1349     using variant_base = detail::variant_cc_base<T...>;
1350     using variant_base::variant_base;
1351 
1352 public:
1353 
1354     // constructors
1355 
1356     variant_ca_base_impl() = default;
1357     variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1358     variant_ca_base_impl( variant_ca_base_impl && ) = default;
1359 
1360     // copy assignment
1361 
1362 private:
1363 
1364     struct L3
1365     {
1366         variant_base * this_;
1367         variant_base const & r;
1368 
operator ()boost::variant2::detail::variant_ca_base_impl::L31369         template<class I> void operator()( I i ) const
1370         {
1371             this_->template emplace<I::value>( r._get_impl( i ) );
1372         }
1373     };
1374 
1375 public:
1376 
operator =boost::variant2::detail::variant_ca_base_impl1377     BOOST_CXX14_CONSTEXPR variant_ca_base_impl& operator=( variant_ca_base_impl const & r )
1378         noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
1379     {
1380         mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
1381         return *this;
1382     }
1383 
1384     // move assignment
1385 
1386     variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1387 };
1388 
1389 // variant_mc_base
1390 
1391 template<bool MoveConstructible, bool TriviallyMoveConstructible, class... T> struct variant_mc_base_impl;
1392 
1393 template<class... T> using variant_mc_base = variant_mc_base_impl<
1394     mp11::mp_all<std::is_move_constructible<T>...>::value,
1395     mp11::mp_all<detail::is_trivially_move_constructible<T>...>::value,
1396     T...>;
1397 
1398 template<class... T> struct variant_mc_base_impl<true, true, T...>: public variant_ca_base<T...>
1399 {
1400     using variant_base = detail::variant_ca_base<T...>;
1401     using variant_base::variant_base;
1402 
1403     variant_mc_base_impl() = default;
1404     variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1405     variant_mc_base_impl( variant_mc_base_impl && ) = default;
1406     variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
1407     variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1408 };
1409 
1410 template<bool B, class... T> struct variant_mc_base_impl<false, B, T...>: public variant_ca_base<T...>
1411 {
1412     using variant_base = detail::variant_ca_base<T...>;
1413     using variant_base::variant_base;
1414 
1415     variant_mc_base_impl() = default;
1416     variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1417     variant_mc_base_impl( variant_mc_base_impl && ) = delete;
1418     variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
1419     variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1420 };
1421 
1422 template<class... T> struct variant_mc_base_impl<true, false, T...>: public variant_ca_base<T...>
1423 {
1424     using variant_base = detail::variant_ca_base<T...>;
1425     using variant_base::variant_base;
1426 
1427 public:
1428 
1429     // constructors
1430 
1431     variant_mc_base_impl() = default;
1432     variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1433 
1434     // move constructor
1435 
1436 private:
1437 
1438     struct L2
1439     {
1440         variant_base * this_;
1441         variant_base & r;
1442 
operator ()boost::variant2::detail::variant_mc_base_impl::L21443         template<class I> void operator()( I i ) const
1444         {
1445             this_->_replace( i, std::move( r._get_impl( i ) ) );
1446         }
1447     };
1448 
1449 public:
1450 
variant_mc_base_implboost::variant2::detail::variant_mc_base_impl1451     variant_mc_base_impl( variant_mc_base_impl && r )
1452         noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
1453     {
1454         mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
1455     }
1456 
1457     // assignment
1458 
1459     variant_mc_base_impl& operator=( variant_mc_base_impl const & ) = default;
1460     variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1461 };
1462 
1463 // variant_ma_base
1464 
1465 template<bool MoveAssignable, bool TriviallyMoveAssignable, class... T> struct variant_ma_base_impl;
1466 
1467 template<class... T> using variant_ma_base = variant_ma_base_impl<
1468     mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>::value,
1469     mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>::value,
1470     T...>;
1471 
1472 template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>
1473 {
1474     using variant_base = detail::variant_mc_base<T...>;
1475     using variant_base::variant_base;
1476 
1477     variant_ma_base_impl() = default;
1478     variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1479     variant_ma_base_impl( variant_ma_base_impl && ) = default;
1480     variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
1481     variant_ma_base_impl& operator=( variant_ma_base_impl && ) = default;
1482 };
1483 
1484 template<bool B, class... T> struct variant_ma_base_impl<false, B, T...>: public variant_mc_base<T...>
1485 {
1486     using variant_base = detail::variant_mc_base<T...>;
1487     using variant_base::variant_base;
1488 
1489     variant_ma_base_impl() = default;
1490     variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1491     variant_ma_base_impl( variant_ma_base_impl && ) = default;
1492     variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
1493     variant_ma_base_impl& operator=( variant_ma_base_impl && ) = delete;
1494 };
1495 
1496 template<class... T> struct variant_ma_base_impl<true, false, T...>: public variant_mc_base<T...>
1497 {
1498     using variant_base = detail::variant_mc_base<T...>;
1499     using variant_base::variant_base;
1500 
1501 public:
1502 
1503     // constructors
1504 
1505     variant_ma_base_impl() = default;
1506     variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1507     variant_ma_base_impl( variant_ma_base_impl && ) = default;
1508 
1509     // copy assignment
1510 
1511     variant_ma_base_impl& operator=( variant_ma_base_impl const & ) = default;
1512 
1513     // move assignment
1514 
1515 private:
1516 
1517     struct L4
1518     {
1519         variant_base * this_;
1520         variant_base & r;
1521 
operator ()boost::variant2::detail::variant_ma_base_impl::L41522         template<class I> void operator()( I i ) const
1523         {
1524             this_->template emplace<I::value>( std::move( r._get_impl( i ) ) );
1525         }
1526     };
1527 
1528 public:
1529 
operator =boost::variant2::detail::variant_ma_base_impl1530     variant_ma_base_impl& operator=( variant_ma_base_impl && r )
1531         noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
1532     {
1533         mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
1534         return *this;
1535     }
1536 };
1537 
1538 } // namespace detail
1539 
1540 // variant
1541 
1542 template<class... T> class variant: private detail::variant_ma_base<T...>
1543 {
1544 private:
1545 
1546     using variant_base = detail::variant_ma_base<T...>;
1547 
1548 public:
1549 
1550     // constructors
1551 
1552     template<class E1 = void, class E2 = mp11::mp_if<std::is_default_constructible< mp11::mp_first<variant<T...>> >, E1>>
variant()1553     constexpr variant()
1554         noexcept( std::is_nothrow_default_constructible< mp11::mp_first<variant<T...>> >::value )
1555         : variant_base( mp11::mp_size_t<0>() )
1556     {
1557     }
1558 
1559     // variant( variant const& ) = default;
1560     // variant( variant && ) = default;
1561 
1562     template<class U,
1563         class Ud = typename std::decay<U>::type,
1564         class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
1565         class V = detail::resolve_overload_type<U&&, T...>,
1566         class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
1567         >
variant(U && u)1568     constexpr variant( U&& u )
1569         noexcept( std::is_nothrow_constructible<V, U&&>::value )
1570         : variant_base( detail::resolve_overload_index<U&&, T...>(), std::forward<U>(u) )
1571     {
1572     }
1573 
1574     template<class U, class... A, class I = mp11::mp_find<variant<T...>, U>, class E = typename std::enable_if<std::is_constructible<U, A&&...>::value>::type>
variant(in_place_type_t<U>,A &&...a)1575     constexpr explicit variant( in_place_type_t<U>, A&&... a ): variant_base( I(), std::forward<A>(a)... )
1576     {
1577     }
1578 
1579     template<class U, class V, class... A, class I = mp11::mp_find<variant<T...>, U>, class E = typename std::enable_if<std::is_constructible<U, std::initializer_list<V>&, A&&...>::value>::type>
variant(in_place_type_t<U>,std::initializer_list<V> il,A &&...a)1580     constexpr explicit variant( in_place_type_t<U>, std::initializer_list<V> il, A&&... a ): variant_base( I(), il, std::forward<A>(a)... )
1581     {
1582     }
1583 
1584     template<std::size_t I, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, A&&...>::value>::type>
variant(in_place_index_t<I>,A &&...a)1585     constexpr explicit variant( in_place_index_t<I>, A&&... a ): variant_base( mp11::mp_size_t<I>(), std::forward<A>(a)... )
1586     {
1587     }
1588 
1589     template<std::size_t I, class V, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, std::initializer_list<V>&, A&&...>::value>::type>
variant(in_place_index_t<I>,std::initializer_list<V> il,A &&...a)1590     constexpr explicit variant( in_place_index_t<I>, std::initializer_list<V> il, A&&... a ): variant_base( mp11::mp_size_t<I>(), il, std::forward<A>(a)... )
1591     {
1592     }
1593 
1594     // assignment
1595 
1596     // variant& operator=( variant const& ) = default;
1597     // variant& operator=( variant && ) = default;
1598 
1599     template<class U,
1600         class E1 = typename std::enable_if<!std::is_same<typename std::decay<U>::type, variant>::value>::type,
1601         class V = detail::resolve_overload_type<U, T...>,
1602         class E2 = typename std::enable_if<std::is_assignable<V&, U&&>::value && std::is_constructible<V, U&&>::value>::type
1603     >
operator =(U && u)1604     BOOST_CXX14_CONSTEXPR variant& operator=( U&& u )
1605         noexcept( std::is_nothrow_constructible<V, U&&>::value )
1606     {
1607         std::size_t const I = detail::resolve_overload_index<U, T...>::value;
1608         this->template emplace<I>( std::forward<U>(u) );
1609         return *this;
1610     }
1611 
1612     // modifiers
1613 
1614     template<class U, class... A,
1615         class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, A&&...>::value >::type>
emplace(A &&...a)1616     BOOST_CXX14_CONSTEXPR U& emplace( A&&... a )
1617     {
1618         using I = mp11::mp_find<variant<T...>, U>;
1619         variant_base::template emplace<I::value>( std::forward<A>(a)... );
1620         return _get_impl( I() );
1621     }
1622 
1623     template<class U, class V, class... A,
1624         class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, std::initializer_list<V>&, A&&...>::value >::type>
emplace(std::initializer_list<V> il,A &&...a)1625     BOOST_CXX14_CONSTEXPR U& emplace( std::initializer_list<V> il, A&&... a )
1626     {
1627         using I = mp11::mp_find<variant<T...>, U>;
1628         variant_base::template emplace<I::value>( il, std::forward<A>(a)... );
1629         return _get_impl( I() );
1630     }
1631 
1632     template<std::size_t I, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, A&&...>::value>::type>
emplace(A &&...a)1633     BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( A&&... a )
1634     {
1635         variant_base::template emplace<I>( std::forward<A>(a)... );
1636         return _get_impl( mp11::mp_size_t<I>() );
1637     }
1638 
1639     template<std::size_t I, class V, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, std::initializer_list<V>&, A&&...>::value>::type>
emplace(std::initializer_list<V> il,A &&...a)1640     BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( std::initializer_list<V> il, A&&... a )
1641     {
1642         variant_base::template emplace<I>( il, std::forward<A>(a)... );
1643         return _get_impl( mp11::mp_size_t<I>() );
1644     }
1645 
1646     // value status
1647 
valueless_by_exception() const1648     constexpr bool valueless_by_exception() const noexcept
1649     {
1650         return false;
1651     }
1652 
1653     using variant_base::index;
1654 
1655     // swap
1656 
1657 private:
1658 
1659     struct L5
1660     {
1661         variant * this_;
1662         variant & r;
1663 
operator ()boost::variant2::variant::L51664         template<class I> void operator()( I i ) const
1665         {
1666             using std::swap;
1667             swap( this_->_get_impl( i ), r._get_impl( i ) );
1668         }
1669     };
1670 
1671 public:
1672 
swap(variant & r)1673     void swap( variant& r ) noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>..., detail::is_nothrow_swappable<T>...>::value )
1674     {
1675         if( index() == r.index() )
1676         {
1677             mp11::mp_with_index<sizeof...(T)>( index(), L5{ this, r } );
1678         }
1679         else
1680         {
1681             variant tmp( std::move(*this) );
1682             *this = std::move( r );
1683             r = std::move( tmp );
1684         }
1685     }
1686 
1687     // private accessors
1688 
1689     using variant_base::_get_impl;
1690 
1691     // converting constructors (extension)
1692 
1693 private:
1694 
1695     template<class... U> struct L6
1696     {
1697         variant_base * this_;
1698         variant<U...> const & r;
1699 
operator ()boost::variant2::variant::L61700         template<class I> void operator()( I i ) const
1701         {
1702             using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
1703             this_->_replace( J{}, r._get_impl( i ) );
1704         }
1705     };
1706 
1707 public:
1708 
1709     template<class... U,
1710         class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
variant(variant<U...> const & r)1711     variant( variant<U...> const& r )
1712         noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<U>...>::value )
1713     {
1714         mp11::mp_with_index<sizeof...(U)>( r.index(), L6<U...>{ this, r } );
1715     }
1716 
1717 private:
1718 
1719     template<class... U> struct L7
1720     {
1721         variant_base * this_;
1722         variant<U...> & r;
1723 
operator ()boost::variant2::variant::L71724         template<class I> void operator()( I i ) const
1725         {
1726             using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
1727             this_->_replace( J{}, std::move( r._get_impl( i ) ) );
1728         }
1729     };
1730 
1731 public:
1732 
1733     template<class... U,
1734         class E2 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
variant(variant<U...> && r)1735     variant( variant<U...> && r )
1736         noexcept( mp11::mp_all<std::is_nothrow_move_constructible<U>...>::value )
1737     {
1738         mp11::mp_with_index<sizeof...(U)>( r.index(), L7<U...>{ this, r } );
1739     }
1740 
1741     // subset (extension)
1742 
1743 private:
1744 
_subset_impl(mp11::mp_size_t<J>,V && v)1745     template<class... U, class V, std::size_t J, class E = typename std::enable_if<J != sizeof...(U)>::type> static constexpr variant<U...> _subset_impl( mp11::mp_size_t<J>, V && v )
1746     {
1747         return variant<U...>( in_place_index_t<J>(), std::forward<V>(v) );
1748     }
1749 
_subset_impl(mp11::mp_size_t<sizeof...(U)>,V &&)1750     template<class... U, class V> static variant<U...> _subset_impl( mp11::mp_size_t<sizeof...(U)>, V && /*v*/ )
1751     {
1752         detail::throw_bad_variant_access();
1753     }
1754 
1755 private:
1756 
1757     template<class... U> struct L8
1758     {
1759         variant * this_;
1760 
operator ()boost::variant2::variant::L81761         template<class I> variant<U...> operator()( I i ) const
1762         {
1763             using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1764             return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
1765         }
1766     };
1767 
1768 public:
1769 
1770     template<class... U,
1771         class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
subset()1772     BOOST_CXX14_CONSTEXPR variant<U...> subset() &
1773     {
1774         return mp11::mp_with_index<sizeof...(T)>( index(), L8<U...>{ this } );
1775     }
1776 
1777 private:
1778 
1779     template<class... U> struct L9
1780     {
1781         variant const * this_;
1782 
operator ()boost::variant2::variant::L91783         template<class I> variant<U...> operator()( I i ) const
1784         {
1785             using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1786             return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
1787         }
1788     };
1789 
1790 public:
1791 
1792     template<class... U,
1793         class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
subset() const1794     constexpr variant<U...> subset() const&
1795     {
1796         return mp11::mp_with_index<sizeof...(T)>( index(), L9<U...>{ this } );
1797     }
1798 
1799 private:
1800 
1801     template<class... U> struct L10
1802     {
1803         variant * this_;
1804 
operator ()boost::variant2::variant::L101805         template<class I> variant<U...> operator()( I i ) const
1806         {
1807             using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1808             return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
1809         }
1810     };
1811 
1812 public:
1813 
1814     template<class... U,
1815         class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
subset()1816     BOOST_CXX14_CONSTEXPR variant<U...> subset() &&
1817     {
1818         return mp11::mp_with_index<sizeof...(T)>( index(), L10<U...>{ this } );
1819     }
1820 
1821 #if !BOOST_WORKAROUND(BOOST_GCC, < 40900)
1822 
1823     // g++ 4.8 doesn't handle const&& particularly well
1824 
1825 private:
1826 
1827     template<class... U> struct L11
1828     {
1829         variant const * this_;
1830 
operator ()boost::variant2::variant::L111831         template<class I> variant<U...> operator()( I i ) const
1832         {
1833             using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1834             return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
1835         }
1836     };
1837 
1838 public:
1839 
1840     template<class... U,
1841         class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
subset() const1842     constexpr variant<U...> subset() const&&
1843     {
1844         return mp11::mp_with_index<sizeof...(T)>( index(), L11<U...>{ this } );
1845     }
1846 
1847 #endif
1848 };
1849 
1850 // relational operators
1851 
1852 namespace detail
1853 {
1854 
1855 template<class... T> struct eq_L
1856 {
1857     variant<T...> const & v;
1858     variant<T...> const & w;
1859 
operator ()boost::variant2::detail::eq_L1860     template<class I> constexpr bool operator()( I i ) const
1861     {
1862         return v._get_impl( i ) == w._get_impl( i );
1863     }
1864 };
1865 
1866 } // namespace detail
1867 
operator ==(variant<T...> const & v,variant<T...> const & w)1868 template<class... T> constexpr bool operator==( variant<T...> const & v, variant<T...> const & w )
1869 {
1870     return v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::eq_L<T...>{ v, w } );
1871 }
1872 
1873 namespace detail
1874 {
1875 
1876 template<class... T> struct ne_L
1877 {
1878     variant<T...> const & v;
1879     variant<T...> const & w;
1880 
operator ()boost::variant2::detail::ne_L1881     template<class I> constexpr bool operator()( I i ) const
1882     {
1883         return v._get_impl( i ) != w._get_impl( i );
1884     }
1885 };
1886 
1887 } // namespace detail
1888 
operator !=(variant<T...> const & v,variant<T...> const & w)1889 template<class... T> constexpr bool operator!=( variant<T...> const & v, variant<T...> const & w )
1890 {
1891     return v.index() != w.index() || mp11::mp_with_index<sizeof...(T)>( v.index(), detail::ne_L<T...>{ v, w } );
1892 }
1893 
1894 namespace detail
1895 {
1896 
1897 template<class... T> struct lt_L
1898 {
1899     variant<T...> const & v;
1900     variant<T...> const & w;
1901 
operator ()boost::variant2::detail::lt_L1902     template<class I> constexpr bool operator()( I i ) const
1903     {
1904         return v._get_impl( i ) < w._get_impl( i );
1905     }
1906 };
1907 
1908 } // namespace detail
1909 
operator <(variant<T...> const & v,variant<T...> const & w)1910 template<class... T> constexpr bool operator<( variant<T...> const & v, variant<T...> const & w )
1911 {
1912     return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::lt_L<T...>{ v, w } ) );
1913 }
1914 
operator >(variant<T...> const & v,variant<T...> const & w)1915 template<class... T> constexpr bool operator>(  variant<T...> const & v, variant<T...> const & w )
1916 {
1917     return w < v;
1918 }
1919 
1920 namespace detail
1921 {
1922 
1923 template<class... T> struct le_L
1924 {
1925     variant<T...> const & v;
1926     variant<T...> const & w;
1927 
operator ()boost::variant2::detail::le_L1928     template<class I> constexpr bool operator()( I i ) const
1929     {
1930         return v._get_impl( i ) <= w._get_impl( i );
1931     }
1932 };
1933 
1934 } // namespace detail
1935 
operator <=(variant<T...> const & v,variant<T...> const & w)1936 template<class... T> constexpr bool operator<=( variant<T...> const & v, variant<T...> const & w )
1937 {
1938     return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::le_L<T...>{ v, w } ) );
1939 }
1940 
operator >=(variant<T...> const & v,variant<T...> const & w)1941 template<class... T> constexpr bool operator>=( variant<T...> const & v, variant<T...> const & w )
1942 {
1943     return w <= v;
1944 }
1945 
1946 // visitation
1947 namespace detail
1948 {
1949 
1950 template<class T> using remove_cv_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
1951 
1952 template<class... T> variant<T...> const & extract_variant_base_( variant<T...> const & );
1953 
1954 #if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
1955 
1956 template<class V> struct extract_vbase_impl
1957 {
1958     using type = decltype( extract_variant_base_( std::declval<V>() ) );
1959 };
1960 
1961 template<class V> using extract_variant_base = remove_cv_ref_t< typename extract_vbase_impl<V>::type >;
1962 
1963 #else
1964 
1965 template<class V> using extract_variant_base = remove_cv_ref_t< decltype( extract_variant_base_( std::declval<V>() ) ) >;
1966 
1967 #endif
1968 
1969 template<class V> using variant_base_size = variant_size< extract_variant_base<V> >;
1970 
1971 template<class T, class U> struct copy_cv_ref
1972 {
1973     using type = T;
1974 };
1975 
1976 template<class T, class U> struct copy_cv_ref<T, U const>
1977 {
1978     using type = T const;
1979 };
1980 
1981 template<class T, class U> struct copy_cv_ref<T, U volatile>
1982 {
1983     using type = T volatile;
1984 };
1985 
1986 template<class T, class U> struct copy_cv_ref<T, U const volatile>
1987 {
1988     using type = T const volatile;
1989 };
1990 
1991 template<class T, class U> struct copy_cv_ref<T, U&>
1992 {
1993     using type = typename copy_cv_ref<T, U>::type&;
1994 };
1995 
1996 template<class T, class U> struct copy_cv_ref<T, U&&>
1997 {
1998     using type = typename copy_cv_ref<T, U>::type&&;
1999 };
2000 
2001 template<class T, class U> using copy_cv_ref_t = typename copy_cv_ref<T, U>::type;
2002 
2003 template<class F> struct Qret
2004 {
2005     template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
2006 };
2007 
2008 template<class L> using front_if_same = mp11::mp_if<mp11::mp_apply<mp11::mp_same, L>, mp11::mp_front<L>>;
2009 
2010 template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, extract_variant_base<V>, mp11::mp_list<V>>;
2011 
2012 struct deduced {};
2013 
2014 #if !BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
2015 
2016 template<class R, class F, class... V> using Vret = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...> >;
2017 
2018 #else
2019 
2020 template<class R, class F, class... V> struct Vret_impl
2021 {
2022     using type = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...> >;
2023 };
2024 
2025 template<class R, class F, class... V> using Vret = typename Vret_impl<R, F, V...>::type;
2026 
2027 #endif
2028 
2029 } // namespace detail
2030 
visit(F && f)2031 template<class R = detail::deduced, class F> constexpr auto visit( F&& f ) -> detail::Vret<R, F>
2032 {
2033     return std::forward<F>(f)();
2034 }
2035 
2036 namespace detail
2037 {
2038 
2039 template<class R, class F, class V1> struct visit_L1
2040 {
2041     F&& f;
2042     V1&& v1;
2043 
operator ()boost::variant2::detail::visit_L12044     template<class I> auto operator()( I ) const -> Vret<R, F, V1>
2045     {
2046         return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
2047     }
2048 };
2049 
2050 } // namespace detail
2051 
visit(F && f,V1 && v1)2052 template<class R = detail::deduced, class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<R, F, V1>
2053 {
2054     return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L1<R, F, V1>{ std::forward<F>(f), std::forward<V1>(v1) } );
2055 }
2056 
2057 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
2058 
2059 namespace detail
2060 {
2061 
2062 template<class F, class A> struct bind_front_
2063 {
2064     F&& f;
2065     A&& a;
2066 
operator ()boost::variant2::detail::bind_front_2067     template<class... T> auto operator()( T&&... t ) -> decltype( std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... ) )
2068     {
2069         return std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... );
2070     }
2071 };
2072 
bind_front(F && f,A && a)2073 template<class F, class A> bind_front_<F, A> bind_front( F&& f, A&& a )
2074 {
2075     return bind_front_<F, A>{ std::forward<F>(f), std::forward<A>(a) };
2076 }
2077 
2078 template<class R, class F, class V1, class V2> struct visit_L2
2079 {
2080     F&& f;
2081 
2082     V1&& v1;
2083     V2&& v2;
2084 
operator ()boost::variant2::detail::visit_L22085     template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2>
2086     {
2087         auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2088 		return visit<R>( f2, std::forward<V2>(v2) );
2089     }
2090 };
2091 
2092 } // namespace detail
2093 
visit(F && f,V1 && v1,V2 && v2)2094 template<class R = detail::deduced, class F, class V1, class V2> constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> detail::Vret<R, F, V1, V2>
2095 {
2096     return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L2<R, F, V1, V2>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2) } );
2097 }
2098 
2099 namespace detail
2100 {
2101 
2102 template<class R, class F, class V1, class V2, class V3> struct visit_L3
2103 {
2104     F&& f;
2105 
2106     V1&& v1;
2107     V2&& v2;
2108     V3&& v3;
2109 
operator ()boost::variant2::detail::visit_L32110     template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3>
2111     {
2112         auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2113         return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
2114     }
2115 };
2116 
2117 } // namespace detail
2118 
visit(F && f,V1 && v1,V2 && v2,V3 && v3)2119 template<class R = detail::deduced, class F, class V1, class V2, class V3> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> detail::Vret<R, F, V1, V2, V3>
2120 {
2121     return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L3<R, F, V1, V2, V3>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3) } );
2122 }
2123 
2124 namespace detail
2125 {
2126 
2127 template<class R, class F, class V1, class V2, class V3, class V4> struct visit_L4
2128 {
2129     F&& f;
2130 
2131     V1&& v1;
2132     V2&& v2;
2133     V3&& v3;
2134     V4&& v4;
2135 
operator ()boost::variant2::detail::visit_L42136     template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3, V4>
2137     {
2138         auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2139         return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
2140     }
2141 };
2142 
2143 } // namespace detail
2144 
visit(F && f,V1 && v1,V2 && v2,V3 && v3,V4 && v4)2145 template<class R = detail::deduced, class F, class V1, class V2, class V3, class V4> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3, V4&& v4 ) -> detail::Vret<R, F, V1, V2, V3, V4>
2146 {
2147     return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L4<R, F, V1, V2, V3, V4>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) } );
2148 }
2149 
2150 #else
2151 
visit(F && f,V1 && v1,V2 && v2,V &&...v)2152 template<class R = detail::deduced, class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V&&... v ) -> detail::Vret<R, F, V1, V2, V...>
2153 {
2154     return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), [&]( auto I ){
2155 
2156         auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( detail::unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
2157         return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
2158 
2159     });
2160 }
2161 
2162 #endif
2163 
2164 // specialized algorithms
2165 template<class... T,
2166     class E = typename std::enable_if<mp11::mp_all<std::is_move_constructible<T>..., detail::is_swappable<T>...>::value>::type>
swap(variant<T...> & v,variant<T...> & w)2167 void swap( variant<T...> & v, variant<T...> & w )
2168     noexcept( noexcept(v.swap(w)) )
2169 {
2170     v.swap( w );
2171 }
2172 
2173 // hashing support
2174 
2175 namespace detail
2176 {
2177 
2178 template<class V> struct hash_value_L
2179 {
2180     V const & v;
2181 
operator ()boost::variant2::detail::hash_value_L2182     template<class I> std::size_t operator()( I ) const
2183     {
2184         boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
2185         boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
2186 
2187         // index
2188 
2189         hv ^= I::value;
2190         hv *= prime;
2191 
2192         // value
2193 
2194         auto const & t = unsafe_get<I::value>( v );
2195 
2196         hv ^= std::hash<remove_cv_ref_t<decltype(t)>>()( t );
2197         hv *= prime;
2198 
2199         return static_cast<std::size_t>( hv );
2200     }
2201 };
2202 
2203 } // namespace detail
2204 
hash_value(monostate const &)2205 inline std::size_t hash_value( monostate const & )
2206 {
2207     return 0xA7EE4757u;
2208 }
2209 
hash_value(variant<T...> const & v)2210 template<class... T> std::size_t hash_value( variant<T...> const & v )
2211 {
2212     return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< variant<T...> >{ v } );
2213 }
2214 
2215 namespace detail
2216 {
2217 
2218 template<class T> using is_hash_enabled = std::is_default_constructible< std::hash<typename std::remove_const<T>::type> >;
2219 
2220 template<class V, bool E = mp11::mp_all_of<V, is_hash_enabled>::value> struct std_hash_impl;
2221 
2222 template<class V> struct std_hash_impl<V, false>
2223 {
2224     std_hash_impl() = delete;
2225     std_hash_impl( std_hash_impl const& ) = delete;
2226     std_hash_impl& operator=( std_hash_impl const& ) = delete;
2227 };
2228 
2229 template<class V> struct std_hash_impl<V, true>
2230 {
operator ()boost::variant2::detail::std_hash_impl2231     std::size_t operator()( V const & v ) const
2232     {
2233         return hash_value( v );
2234     }
2235 };
2236 
2237 } // namespace detail
2238 
2239 } // namespace variant2
2240 } // namespace boost
2241 
2242 namespace std
2243 {
2244 
2245 template<class... T> struct hash< ::boost::variant2::variant<T...> >: public ::boost::variant2::detail::std_hash_impl< ::boost::variant2::variant<T...> >
2246 {
2247 };
2248 
2249 template<> struct hash< ::boost::variant2::monostate >
2250 {
operator ()std::hash2251     std::size_t operator()( ::boost::variant2::monostate const & v ) const
2252     {
2253         return hash_value( v );
2254     }
2255 };
2256 
2257 } // namespace std
2258 
2259 #if defined(_MSC_VER) && _MSC_VER < 1910
2260 # pragma warning( pop )
2261 #endif
2262 
2263 #endif // #ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
2264