]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/variant2/variant.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / variant2 / variant.hpp
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
50 bad_variant_access() noexcept
51 {
52 }
53
54 char const * what() const noexcept
55 {
56 return "bad_variant_access";
57 }
58 };
59
60 namespace detail
61 {
62
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
84 constexpr bool operator<(monostate, monostate) noexcept { return false; }
85 constexpr bool operator>(monostate, monostate) noexcept { return false; }
86 constexpr bool operator<=(monostate, monostate) noexcept { return true; }
87 constexpr bool operator>=(monostate, monostate) noexcept { return true; }
88 constexpr bool operator==(monostate, monostate) noexcept { return true; }
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
523 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
524 {
525 }
526
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
531 ~variant_storage_impl()
532 {
533 }
534
535 template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a )
536 {
537 ::new( &first_ ) T1( std::forward<A>(a)... );
538 }
539
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
545 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
546 constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
547
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>() ); }
549 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
567 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
568 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
569 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
570 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
571 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
572 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
573 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
574 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
575 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
576 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
577
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
580 ~variant_storage_impl()
581 {
582 }
583
584 template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
585 template<class... A> void emplace( mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
586 template<class... A> void emplace( mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
587 template<class... A> void emplace( mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
588 template<class... A> void emplace( mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
589 template<class... A> void emplace( mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
590 template<class... A> void emplace( mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
591 template<class... A> void emplace( mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
592 template<class... A> void emplace( mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
593 template<class... A> void emplace( mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
594
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
600 BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
601 constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
602
603 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
604 constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
605
606 BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
607 constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
608
609 BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
610 constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
611
612 BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
613 constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
614
615 BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
616 constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
617
618 BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
619 constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
620
621 BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
622 constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
623
624 BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
625 constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
626
627 BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
628 constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
629
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>() ); }
631 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
640 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
641 {
642 }
643
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
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
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
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
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
668 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
669 constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
670
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>() ); }
672 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
690 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
691 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
692 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
693 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
694 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
695 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
696 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
697 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
698 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
699 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
700
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
703 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<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)... ); }
705 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<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)... ); }
707 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<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)... ); }
709 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<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)... ); }
711 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<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
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
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
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
740 BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
741 constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
742
743 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
744 constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
745
746 BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
747 constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
748
749 BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
750 constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
751
752 BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
753 constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
754
755 BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
756 constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
757
758 BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
759 constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
760
761 BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
762 constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
763
764 BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
765 constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
766
767 BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
768 constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
769
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>() ); }
771 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
820 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
821 {
822 }
823
824 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
829 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
835 constexpr std::size_t index() const noexcept
836 {
837 return ix_ - 1;
838 }
839
840 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
849 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
857 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
865 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
875 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
891 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
892 {
893 }
894
895 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
900 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
906 constexpr std::size_t index() const noexcept
907 {
908 return ix_ >= 0? ix_ - 1: -ix_ - 1;
909 }
910
911 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
921 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
930 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
953 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
954 {
955 }
956
957 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
962 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
977 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
984 void _destroy() noexcept
985 {
986 if( ix_ > 0 )
987 {
988 mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
989 }
990 }
991
992 ~variant_base_impl() noexcept
993 {
994 _destroy();
995 }
996
997 constexpr std::size_t index() const noexcept
998 {
999 return ix_ - 1;
1000 }
1001
1002 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
1011 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
1019 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
1043 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
1044 {
1045 }
1046
1047 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
1052 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
1067 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
1078 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
1085 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
1097 ~variant_base_impl() noexcept
1098 {
1099 _destroy();
1100 }
1101
1102 constexpr std::size_t index() const noexcept
1103 {
1104 return ix_ >= 0? ix_ - 1: -ix_ - 1;
1105 }
1106
1107 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
1117 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
1126 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
1289 template<class I> void operator()( I i ) const
1290 {
1291 this_->_replace( i, r._get_impl( i ) );
1292 }
1293 };
1294
1295 public:
1296
1297 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
1369 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
1377 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
1443 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
1451 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
1522 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
1530 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>>
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 >
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>
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>
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>
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>
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 >
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>
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>
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>
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>
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
1648 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
1664 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
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
1700 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> >
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
1724 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> >
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
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
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
1761 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> >
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
1783 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> >
1794 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
1805 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> >
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
1831 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> >
1842 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
1860 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
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
1881 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
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
1902 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
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
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
1928 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
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
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
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
2044 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
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
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
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
2085 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
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
2110 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
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
2136 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
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
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>
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
2182 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
2205 inline std::size_t hash_value( monostate const & )
2206 {
2207 return 0xA7EE4757u;
2208 }
2209
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 {
2231 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 {
2251 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