mpark_variant.hpp (85328B)
1 // Changed from mpark variant v1.3.0: use std::in_place* 2 3 // MPark.Variant 4 // 5 // Copyright Michael Park, 2015-2017 6 // 7 // Distributed under the Boost Software License, Version 1.0. 8 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 9 10 #ifndef MPARK_VARIANT_HPP 11 #define MPARK_VARIANT_HPP 12 13 /* 14 variant synopsis 15 16 namespace std { 17 18 // 20.7.2, class template variant 19 template <class... Types> 20 class variant { 21 public: 22 23 // 20.7.2.1, constructors 24 constexpr variant() noexcept(see below); 25 variant(const variant&); 26 variant(variant&&) noexcept(see below); 27 28 template <class T> constexpr variant(T&&) noexcept(see below); 29 30 template <class T, class... Args> 31 constexpr explicit variant(in_place_type_t<T>, Args&&...); 32 33 template <class T, class U, class... Args> 34 constexpr explicit variant( 35 in_place_type_t<T>, initializer_list<U>, Args&&...); 36 37 template <size_t I, class... Args> 38 constexpr explicit variant(in_place_index_t<I>, Args&&...); 39 40 template <size_t I, class U, class... Args> 41 constexpr explicit variant( 42 in_place_index_t<I>, initializer_list<U>, Args&&...); 43 44 // 20.7.2.2, destructor 45 ~variant(); 46 47 // 20.7.2.3, assignment 48 variant& operator=(const variant&); 49 variant& operator=(variant&&) noexcept(see below); 50 51 template <class T> variant& operator=(T&&) noexcept(see below); 52 53 // 20.7.2.4, modifiers 54 template <class T, class... Args> 55 T& emplace(Args&&...); 56 57 template <class T, class U, class... Args> 58 T& emplace(initializer_list<U>, Args&&...); 59 60 template <size_t I, class... Args> 61 variant_alternative<I, variant>& emplace(Args&&...); 62 63 template <size_t I, class U, class... Args> 64 variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...); 65 66 // 20.7.2.5, value status 67 constexpr bool valueless_by_exception() const noexcept; 68 constexpr size_t index() const noexcept; 69 70 // 20.7.2.6, swap 71 void swap(variant&) noexcept(see below); 72 }; 73 74 // 20.7.3, variant helper classes 75 template <class T> struct variant_size; // undefined 76 77 template <class T> 78 constexpr size_t variant_size_v = variant_size<T>::value; 79 80 template <class T> struct variant_size<const T>; 81 template <class T> struct variant_size<volatile T>; 82 template <class T> struct variant_size<const volatile T>; 83 84 template <class... Types> 85 struct variant_size<variant<Types...>>; 86 87 template <size_t I, class T> struct variant_alternative; // undefined 88 89 template <size_t I, class T> 90 using variant_alternative_t = typename variant_alternative<I, T>::type; 91 92 template <size_t I, class T> struct variant_alternative<I, const T>; 93 template <size_t I, class T> struct variant_alternative<I, volatile T>; 94 template <size_t I, class T> struct variant_alternative<I, const volatile T>; 95 96 template <size_t I, class... Types> 97 struct variant_alternative<I, variant<Types...>>; 98 99 constexpr size_t variant_npos = -1; 100 101 // 20.7.4, value access 102 template <class T, class... Types> 103 constexpr bool holds_alternative(const variant<Types...>&) noexcept; 104 105 template <size_t I, class... Types> 106 constexpr variant_alternative_t<I, variant<Types...>>& 107 get(variant<Types...>&); 108 109 template <size_t I, class... Types> 110 constexpr variant_alternative_t<I, variant<Types...>>&& 111 get(variant<Types...>&&); 112 113 template <size_t I, class... Types> 114 constexpr variant_alternative_t<I, variant<Types...>> const& 115 get(const variant<Types...>&); 116 117 template <size_t I, class... Types> 118 constexpr variant_alternative_t<I, variant<Types...>> const&& 119 get(const variant<Types...>&&); 120 121 template <class T, class... Types> 122 constexpr T& get(variant<Types...>&); 123 124 template <class T, class... Types> 125 constexpr T&& get(variant<Types...>&&); 126 127 template <class T, class... Types> 128 constexpr const T& get(const variant<Types...>&); 129 130 template <class T, class... Types> 131 constexpr const T&& get(const variant<Types...>&&); 132 133 template <size_t I, class... Types> 134 constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> 135 get_if(variant<Types...>*) noexcept; 136 137 template <size_t I, class... Types> 138 constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> 139 get_if(const variant<Types...>*) noexcept; 140 141 template <class T, class... Types> 142 constexpr add_pointer_t<T> 143 get_if(variant<Types...>*) noexcept; 144 145 template <class T, class... Types> 146 constexpr add_pointer_t<const T> 147 get_if(const variant<Types...>*) noexcept; 148 149 // 20.7.5, relational operators 150 template <class... Types> 151 constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); 152 153 template <class... Types> 154 constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); 155 156 template <class... Types> 157 constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); 158 159 template <class... Types> 160 constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); 161 162 template <class... Types> 163 constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); 164 165 template <class... Types> 166 constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); 167 168 // 20.7.6, visitation 169 template <class Visitor, class... Variants> 170 constexpr see below visit(Visitor&&, Variants&&...); 171 172 // 20.7.7, class monostate 173 struct monostate; 174 175 // 20.7.8, monostate relational operators 176 constexpr bool operator<(monostate, monostate) noexcept; 177 constexpr bool operator>(monostate, monostate) noexcept; 178 constexpr bool operator<=(monostate, monostate) noexcept; 179 constexpr bool operator>=(monostate, monostate) noexcept; 180 constexpr bool operator==(monostate, monostate) noexcept; 181 constexpr bool operator!=(monostate, monostate) noexcept; 182 183 // 20.7.9, specialized algorithms 184 template <class... Types> 185 void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); 186 187 // 20.7.10, class bad_variant_access 188 class bad_variant_access; 189 190 // 20.7.11, hash support 191 template <class T> struct hash; 192 template <class... Types> struct hash<variant<Types...>>; 193 template <> struct hash<monostate>; 194 195 } // namespace std 196 197 */ 198 199 #include <cstddef> 200 #include <exception> 201 #include <functional> 202 #include <initializer_list> 203 #include <new> 204 #include <type_traits> 205 #include <utility> 206 207 // MPark.Variant 208 // 209 // Copyright Michael Park, 2015-2017 210 // 211 // Distributed under the Boost Software License, Version 1.0. 212 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 213 214 #ifndef MPARK_CONFIG_HPP 215 #define MPARK_CONFIG_HPP 216 217 // MSVC 2015 Update 3. 218 #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) 219 #error "MPark.Variant requires C++11 support." 220 #endif 221 222 #ifndef __has_builtin 223 #define __has_builtin(x) 0 224 #endif 225 226 #ifndef __has_include 227 #define __has_include(x) 0 228 #endif 229 230 #ifndef __has_feature 231 #define __has_feature(x) 0 232 #endif 233 234 #if __has_builtin(__builtin_addressof) || \ 235 (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) 236 #define MPARK_BUILTIN_ADDRESSOF 237 #endif 238 239 #if __has_builtin(__builtin_unreachable) 240 #define MPARK_BUILTIN_UNREACHABLE 241 #endif 242 243 #if __has_builtin(__type_pack_element) 244 #define MPARK_TYPE_PACK_ELEMENT 245 #endif 246 247 #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 248 #define MPARK_CPP14_CONSTEXPR 249 #endif 250 251 #if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ 252 (defined(_MSC_VER) && defined(_CPPUNWIND)) 253 #define MPARK_EXCEPTIONS 254 #endif 255 256 #if defined(__cpp_generic_lambdas) || defined(_MSC_VER) 257 #define MPARK_GENERIC_LAMBDAS 258 #endif 259 260 #if defined(__cpp_lib_integer_sequence) 261 #define MPARK_INTEGER_SEQUENCE 262 #endif 263 264 #if defined(__cpp_return_type_deduction) || defined(_MSC_VER) 265 #define MPARK_RETURN_TYPE_DEDUCTION 266 #endif 267 268 #if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER) 269 #define MPARK_TRANSPARENT_OPERATORS 270 #endif 271 272 #if defined(__cpp_variable_templates) || defined(_MSC_VER) 273 #define MPARK_VARIABLE_TEMPLATES 274 #endif 275 276 #if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5 277 #define MPARK_TRIVIALITY_TYPE_TRAITS 278 #endif 279 280 #endif // MPARK_CONFIG_HPP 281 282 // MPark.Variant 283 // 284 // Copyright Michael Park, 2015-2017 285 // 286 // Distributed under the Boost Software License, Version 1.0. 287 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 288 289 #ifndef MPARK_IN_PLACE_HPP 290 #define MPARK_IN_PLACE_HPP 291 292 #include <utility> 293 294 namespace mpark { 295 296 using std::in_place_t; 297 using std::in_place_index_t; 298 using std::in_place_type_t; 299 300 } // namespace mpark 301 302 #endif // MPARK_IN_PLACE_HPP 303 304 // MPark.Variant 305 // 306 // Copyright Michael Park, 2015-2017 307 // 308 // Distributed under the Boost Software License, Version 1.0. 309 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 310 311 #ifndef MPARK_LIB_HPP 312 #define MPARK_LIB_HPP 313 314 #include <memory> 315 #include <functional> 316 #include <type_traits> 317 #include <utility> 318 319 320 #define RETURN(...) \ 321 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \ 322 return __VA_ARGS__; \ 323 } 324 325 namespace mpark { 326 namespace lib { 327 template <typename T> 328 struct identity { using type = T; }; 329 330 inline namespace cpp14 { 331 template <typename T, std::size_t N> 332 struct array { 333 constexpr const T &operator[](std::size_t index) const { 334 return data[index]; 335 } 336 337 T data[N == 0 ? 1 : N]; 338 }; 339 340 template <typename T> 341 using add_pointer_t = typename std::add_pointer<T>::type; 342 343 template <typename... Ts> 344 using common_type_t = typename std::common_type<Ts...>::type; 345 346 template <typename T> 347 using decay_t = typename std::decay<T>::type; 348 349 template <bool B, typename T = void> 350 using enable_if_t = typename std::enable_if<B, T>::type; 351 352 template <typename T> 353 using remove_const_t = typename std::remove_const<T>::type; 354 355 template <typename T> 356 using remove_reference_t = typename std::remove_reference<T>::type; 357 358 template <typename T> 359 inline constexpr T &&forward(remove_reference_t<T> &t) noexcept { 360 return static_cast<T &&>(t); 361 } 362 363 template <typename T> 364 inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept { 365 static_assert(!std::is_lvalue_reference<T>::value, 366 "can not forward an rvalue as an lvalue"); 367 return static_cast<T &&>(t); 368 } 369 370 template <typename T> 371 inline constexpr remove_reference_t<T> &&move(T &&t) noexcept { 372 return static_cast<remove_reference_t<T> &&>(t); 373 } 374 375 #ifdef MPARK_INTEGER_SEQUENCE 376 using std::integer_sequence; 377 using std::index_sequence; 378 using std::make_index_sequence; 379 using std::index_sequence_for; 380 #else 381 template <typename T, T... Is> 382 struct integer_sequence { 383 using value_type = T; 384 static constexpr std::size_t size() noexcept { return sizeof...(Is); } 385 }; 386 387 template <std::size_t... Is> 388 using index_sequence = integer_sequence<std::size_t, Is...>; 389 390 template <typename Lhs, typename Rhs> 391 struct make_index_sequence_concat; 392 393 template <std::size_t... Lhs, std::size_t... Rhs> 394 struct make_index_sequence_concat<index_sequence<Lhs...>, 395 index_sequence<Rhs...>> 396 : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {}; 397 398 template <std::size_t N> 399 struct make_index_sequence_impl; 400 401 template <std::size_t N> 402 using make_index_sequence = typename make_index_sequence_impl<N>::type; 403 404 template <std::size_t N> 405 struct make_index_sequence_impl 406 : make_index_sequence_concat<make_index_sequence<N / 2>, 407 make_index_sequence<N - (N / 2)>> {}; 408 409 template <> 410 struct make_index_sequence_impl<0> : identity<index_sequence<>> {}; 411 412 template <> 413 struct make_index_sequence_impl<1> : identity<index_sequence<0>> {}; 414 415 template <typename... Ts> 416 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; 417 #endif 418 419 // <functional> 420 #ifdef MPARK_TRANSPARENT_OPERATORS 421 using equal_to = std::equal_to<>; 422 #else 423 struct equal_to { 424 template <typename Lhs, typename Rhs> 425 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const 426 RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs)) 427 }; 428 #endif 429 430 #ifdef MPARK_TRANSPARENT_OPERATORS 431 using not_equal_to = std::not_equal_to<>; 432 #else 433 struct not_equal_to { 434 template <typename Lhs, typename Rhs> 435 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const 436 RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs)) 437 }; 438 #endif 439 440 #ifdef MPARK_TRANSPARENT_OPERATORS 441 using less = std::less<>; 442 #else 443 struct less { 444 template <typename Lhs, typename Rhs> 445 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const 446 RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs)) 447 }; 448 #endif 449 450 #ifdef MPARK_TRANSPARENT_OPERATORS 451 using greater = std::greater<>; 452 #else 453 struct greater { 454 template <typename Lhs, typename Rhs> 455 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const 456 RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs)) 457 }; 458 #endif 459 460 #ifdef MPARK_TRANSPARENT_OPERATORS 461 using less_equal = std::less_equal<>; 462 #else 463 struct less_equal { 464 template <typename Lhs, typename Rhs> 465 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const 466 RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs)) 467 }; 468 #endif 469 470 #ifdef MPARK_TRANSPARENT_OPERATORS 471 using greater_equal = std::greater_equal<>; 472 #else 473 struct greater_equal { 474 template <typename Lhs, typename Rhs> 475 inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const 476 RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs)) 477 }; 478 #endif 479 } // namespace cpp14 480 481 inline namespace cpp17 { 482 483 // <type_traits> 484 template <bool B> 485 using bool_constant = std::integral_constant<bool, B>; 486 487 template <typename...> 488 struct voider : identity<void> {}; 489 490 template <typename... Ts> 491 using void_t = typename voider<Ts...>::type; 492 493 namespace detail { 494 namespace swappable { 495 496 using std::swap; 497 498 template <typename T> 499 struct is_swappable { 500 private: 501 template <typename U, 502 typename = decltype(swap(std::declval<U &>(), 503 std::declval<U &>()))> 504 inline static std::true_type test(int); 505 506 template <typename U> 507 inline static std::false_type test(...); 508 509 public: 510 static constexpr bool value = decltype(test<T>(0))::value; 511 }; 512 513 template <typename T, bool = is_swappable<T>::value> 514 struct is_nothrow_swappable { 515 static constexpr bool value = 516 noexcept(swap(std::declval<T &>(), std::declval<T &>())); 517 }; 518 519 template <typename T> 520 struct is_nothrow_swappable<T, false> : std::false_type {}; 521 522 } // namespace swappable 523 } // namespace detail 524 525 using detail::swappable::is_swappable; 526 using detail::swappable::is_nothrow_swappable; 527 528 // <functional> 529 #ifdef _MSC_VER 530 #pragma warning(push) 531 #pragma warning(disable : 4100) 532 #endif 533 template <typename F, typename... As> 534 inline constexpr auto invoke(F &&f, As &&... as) 535 RETURN(lib::forward<F>(f)(lib::forward<As>(as)...)) 536 #ifdef _MSC_VER 537 #pragma warning(pop) 538 #endif 539 540 template <typename B, typename T, typename D> 541 inline constexpr auto invoke(T B::*pmv, D &&d) 542 RETURN(lib::forward<D>(d).*pmv) 543 544 template <typename Pmv, typename Ptr> 545 inline constexpr auto invoke(Pmv pmv, Ptr &&ptr) 546 RETURN((*lib::forward<Ptr>(ptr)).*pmv) 547 548 template <typename B, typename T, typename D, typename... As> 549 inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as) 550 RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...)) 551 552 template <typename Pmf, typename Ptr, typename... As> 553 inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as) 554 RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...)) 555 556 namespace detail { 557 558 template <typename Void, typename, typename...> 559 struct invoke_result {}; 560 561 template <typename F, typename... Args> 562 struct invoke_result<void_t<decltype(lib::invoke( 563 std::declval<F>(), std::declval<Args>()...))>, 564 F, 565 Args...> 566 : identity<decltype( 567 lib::invoke(std::declval<F>(), std::declval<Args>()...))> {}; 568 569 } // namespace detail 570 571 template <typename F, typename... Args> 572 using invoke_result = detail::invoke_result<void, F, Args...>; 573 574 template <typename F, typename... Args> 575 using invoke_result_t = typename invoke_result<F, Args...>::type; 576 577 namespace detail { 578 579 template <typename Void, typename, typename...> 580 struct is_invocable : std::false_type {}; 581 582 template <typename F, typename... Args> 583 struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> 584 : std::true_type {}; 585 586 template <typename Void, typename, typename, typename...> 587 struct is_invocable_r : std::false_type {}; 588 589 template <typename R, typename F, typename... Args> 590 struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, 591 R, 592 F, 593 Args...> 594 : std::is_convertible<invoke_result_t<F, Args...>, R> {}; 595 596 } // namespace detail 597 598 template <typename F, typename... Args> 599 using is_invocable = detail::is_invocable<void, F, Args...>; 600 601 template <typename R, typename F, typename... Args> 602 using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>; 603 604 // <memory> 605 #ifdef MPARK_BUILTIN_ADDRESSOF 606 template <typename T> 607 inline constexpr T *addressof(T &arg) { 608 return __builtin_addressof(arg); 609 } 610 #else 611 namespace detail { 612 613 namespace has_addressof_impl { 614 615 struct fail; 616 617 template <typename T> 618 inline fail operator&(T &&); 619 620 template <typename T> 621 inline static constexpr bool impl() { 622 return (std::is_class<T>::value || std::is_union<T>::value) && 623 !std::is_same<decltype(&std::declval<T &>()), fail>::value; 624 } 625 626 } // namespace has_addressof_impl 627 628 template <typename T> 629 using has_addressof = bool_constant<has_addressof_impl::impl<T>()>; 630 631 template <typename T> 632 inline constexpr T *addressof(T &arg, std::true_type) { 633 return std::addressof(arg); 634 } 635 636 template <typename T> 637 inline constexpr T *addressof(T &arg, std::false_type) { 638 return &arg; 639 } 640 641 } // namespace detail 642 643 template <typename T> 644 inline constexpr T *addressof(T &arg) { 645 return detail::addressof(arg, detail::has_addressof<T>{}); 646 } 647 #endif 648 649 template <typename T> 650 inline constexpr T *addressof(const T &&) = delete; 651 652 } // namespace cpp17 653 654 template <typename T> 655 struct remove_all_extents : identity<T> {}; 656 657 template <typename T, std::size_t N> 658 struct remove_all_extents<array<T, N>> : remove_all_extents<T> {}; 659 660 template <typename T> 661 using remove_all_extents_t = typename remove_all_extents<T>::type; 662 663 template <std::size_t N> 664 using size_constant = std::integral_constant<std::size_t, N>; 665 666 template <std::size_t I, typename T> 667 struct indexed_type : size_constant<I>, identity<T> {}; 668 669 template <bool... Bs> 670 using all = std::is_same<integer_sequence<bool, true, Bs...>, 671 integer_sequence<bool, Bs..., true>>; 672 673 #ifdef MPARK_TYPE_PACK_ELEMENT 674 template <std::size_t I, typename... Ts> 675 using type_pack_element_t = __type_pack_element<I, Ts...>; 676 #else 677 template <std::size_t I, typename... Ts> 678 struct type_pack_element_impl { 679 private: 680 template <typename> 681 struct set; 682 683 template <std::size_t... Is> 684 struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {}; 685 686 template <typename T> 687 inline static std::enable_if<true, T> impl(indexed_type<I, T>); 688 689 inline static std::enable_if<false> impl(...); 690 691 public: 692 using type = decltype(impl(set<index_sequence_for<Ts...>>{})); 693 }; 694 695 template <std::size_t I, typename... Ts> 696 using type_pack_element = typename type_pack_element_impl<I, Ts...>::type; 697 698 template <std::size_t I, typename... Ts> 699 using type_pack_element_t = typename type_pack_element<I, Ts...>::type; 700 #endif 701 702 #ifdef MPARK_TRIVIALITY_TYPE_TRAITS 703 using std::is_trivially_copy_constructible; 704 using std::is_trivially_move_constructible; 705 using std::is_trivially_copy_assignable; 706 using std::is_trivially_move_assignable; 707 #else 708 template <typename T> 709 struct is_trivially_copy_constructible 710 : bool_constant< 711 std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {}; 712 713 template <typename T> 714 struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; 715 716 template <typename T> 717 struct is_trivially_copy_assignable 718 : bool_constant< 719 std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {}; 720 721 template <typename T> 722 struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; 723 #endif 724 725 template <typename T, bool> 726 struct dependent_type : T {}; 727 728 template <typename Is, std::size_t J> 729 struct push_back; 730 731 template <typename Is, std::size_t J> 732 using push_back_t = typename push_back<Is, J>::type; 733 734 template <std::size_t... Is, std::size_t J> 735 struct push_back<index_sequence<Is...>, J> { 736 using type = index_sequence<Is..., J>; 737 }; 738 739 } // namespace lib 740 } // namespace mpark 741 742 #undef RETURN 743 744 #endif // MPARK_LIB_HPP 745 746 747 namespace mpark { 748 749 #ifdef MPARK_RETURN_TYPE_DEDUCTION 750 751 #define AUTO auto 752 #define AUTO_RETURN(...) { return __VA_ARGS__; } 753 754 #define AUTO_REFREF auto && 755 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } 756 757 #define DECLTYPE_AUTO decltype(auto) 758 #define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } 759 760 #else 761 762 #define AUTO auto 763 #define AUTO_RETURN(...) \ 764 -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; } 765 766 #define AUTO_REFREF auto 767 #define AUTO_REFREF_RETURN(...) \ 768 -> decltype((__VA_ARGS__)) { \ 769 static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \ 770 return __VA_ARGS__; \ 771 } 772 773 #define DECLTYPE_AUTO auto 774 #define DECLTYPE_AUTO_RETURN(...) \ 775 -> decltype(__VA_ARGS__) { return __VA_ARGS__; } 776 777 #endif 778 779 class bad_variant_access : public std::exception { 780 public: 781 virtual const char *what() const noexcept { return "bad_variant_access"; } 782 }; 783 784 [[noreturn]] inline void throw_bad_variant_access() { 785 #ifdef MPARK_EXCEPTIONS 786 throw bad_variant_access{}; 787 #else 788 std::terminate(); 789 #ifdef MPARK_BUILTIN_UNREACHABLE 790 __builtin_unreachable(); 791 #endif 792 #endif 793 } 794 795 template <typename... Ts> 796 class variant; 797 798 template <typename T> 799 struct variant_size; 800 801 #ifdef MPARK_VARIABLE_TEMPLATES 802 template <typename T> 803 constexpr std::size_t variant_size_v = variant_size<T>::value; 804 #endif 805 806 template <typename T> 807 struct variant_size<const T> : variant_size<T> {}; 808 809 template <typename T> 810 struct variant_size<volatile T> : variant_size<T> {}; 811 812 template <typename T> 813 struct variant_size<const volatile T> : variant_size<T> {}; 814 815 template <typename... Ts> 816 struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)> {}; 817 818 template <std::size_t I, typename T> 819 struct variant_alternative; 820 821 template <std::size_t I, typename T> 822 using variant_alternative_t = typename variant_alternative<I, T>::type; 823 824 template <std::size_t I, typename T> 825 struct variant_alternative<I, const T> 826 : std::add_const<variant_alternative_t<I, T>> {}; 827 828 template <std::size_t I, typename T> 829 struct variant_alternative<I, volatile T> 830 : std::add_volatile<variant_alternative_t<I, T>> {}; 831 832 template <std::size_t I, typename T> 833 struct variant_alternative<I, const volatile T> 834 : std::add_cv<variant_alternative_t<I, T>> {}; 835 836 template <std::size_t I, typename... Ts> 837 struct variant_alternative<I, variant<Ts...>> { 838 static_assert(I < sizeof...(Ts), 839 "Index out of bounds in std::variant_alternative<>"); 840 using type = lib::type_pack_element_t<I, Ts...>; 841 }; 842 843 constexpr std::size_t variant_npos = static_cast<std::size_t>(-1); 844 845 namespace detail { 846 847 constexpr std::size_t not_found = static_cast<std::size_t>(-1); 848 constexpr std::size_t ambiguous = static_cast<std::size_t>(-2); 849 850 #ifdef MPARK_CPP14_CONSTEXPR 851 template <typename T, typename... Ts> 852 inline constexpr std::size_t find_index() { 853 constexpr lib::array<bool, sizeof...(Ts)> matches = { 854 {std::is_same<T, Ts>::value...} 855 }; 856 std::size_t result = not_found; 857 for (std::size_t i = 0; i < sizeof...(Ts); ++i) { 858 if (matches[i]) { 859 if (result != not_found) { 860 return ambiguous; 861 } 862 result = i; 863 } 864 } 865 return result; 866 } 867 #else 868 inline constexpr std::size_t find_index_impl(std::size_t result, 869 std::size_t) { 870 return result; 871 } 872 873 template <typename... Bs> 874 inline constexpr std::size_t find_index_impl(std::size_t result, 875 std::size_t idx, 876 bool b, 877 Bs... bs) { 878 return b ? (result != not_found ? ambiguous 879 : find_index_impl(idx, idx + 1, bs...)) 880 : find_index_impl(result, idx + 1, bs...); 881 } 882 883 template <typename T, typename... Ts> 884 inline constexpr std::size_t find_index() { 885 return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...); 886 } 887 #endif 888 889 template <std::size_t I> 890 using find_index_sfinae_impl = 891 lib::enable_if_t<I != not_found && I != ambiguous, 892 lib::size_constant<I>>; 893 894 template <typename T, typename... Ts> 895 using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>; 896 897 template <std::size_t I> 898 struct find_index_checked_impl : lib::size_constant<I> { 899 static_assert(I != not_found, "the specified type is not found."); 900 static_assert(I != ambiguous, "the specified type is ambiguous."); 901 }; 902 903 template <typename T, typename... Ts> 904 using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>; 905 906 struct valueless_t {}; 907 908 enum class Trait { TriviallyAvailable, Available, Unavailable }; 909 910 template <typename T, 911 template <typename> class IsTriviallyAvailable, 912 template <typename> class IsAvailable> 913 inline constexpr Trait trait() { 914 return IsTriviallyAvailable<T>::value 915 ? Trait::TriviallyAvailable 916 : IsAvailable<T>::value ? Trait::Available 917 : Trait::Unavailable; 918 } 919 920 #ifdef MPARK_CPP14_CONSTEXPR 921 template <typename... Traits> 922 inline constexpr Trait common_trait(Traits... traits) { 923 Trait result = Trait::TriviallyAvailable; 924 for (Trait t : {traits...}) { 925 if (static_cast<int>(t) > static_cast<int>(result)) { 926 result = t; 927 } 928 } 929 return result; 930 } 931 #else 932 inline constexpr Trait common_trait_impl(Trait result) { return result; } 933 934 template <typename... Traits> 935 inline constexpr Trait common_trait_impl(Trait result, 936 Trait t, 937 Traits... ts) { 938 return static_cast<int>(t) > static_cast<int>(result) 939 ? common_trait_impl(t, ts...) 940 : common_trait_impl(result, ts...); 941 } 942 943 template <typename... Traits> 944 inline constexpr Trait common_trait(Traits... ts) { 945 return common_trait_impl(Trait::TriviallyAvailable, ts...); 946 } 947 #endif 948 949 template <typename... Ts> 950 struct traits { 951 static constexpr Trait copy_constructible_trait = 952 common_trait(trait<Ts, 953 lib::is_trivially_copy_constructible, 954 std::is_copy_constructible>()...); 955 956 static constexpr Trait move_constructible_trait = 957 common_trait(trait<Ts, 958 lib::is_trivially_move_constructible, 959 std::is_move_constructible>()...); 960 961 static constexpr Trait copy_assignable_trait = 962 common_trait(copy_constructible_trait, 963 trait<Ts, 964 lib::is_trivially_copy_assignable, 965 std::is_copy_assignable>()...); 966 967 static constexpr Trait move_assignable_trait = 968 common_trait(move_constructible_trait, 969 trait<Ts, 970 lib::is_trivially_move_assignable, 971 std::is_move_assignable>()...); 972 973 static constexpr Trait destructible_trait = 974 common_trait(trait<Ts, 975 std::is_trivially_destructible, 976 std::is_destructible>()...); 977 }; 978 979 namespace access { 980 981 struct recursive_union { 982 #ifdef MPARK_RETURN_TYPE_DEDUCTION 983 template <typename V> 984 inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) { 985 return lib::forward<V>(v).head_; 986 } 987 988 template <typename V, std::size_t I> 989 inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) { 990 return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{}); 991 } 992 #else 993 template <std::size_t I, bool Dummy = true> 994 struct get_alt_impl { 995 template <typename V> 996 inline constexpr AUTO_REFREF operator()(V &&v) const 997 AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_)) 998 }; 999 1000 template <bool Dummy> 1001 struct get_alt_impl<0, Dummy> { 1002 template <typename V> 1003 inline constexpr AUTO_REFREF operator()(V &&v) const 1004 AUTO_REFREF_RETURN(lib::forward<V>(v).head_) 1005 }; 1006 1007 template <typename V, std::size_t I> 1008 inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t<I>) 1009 AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v))) 1010 #endif 1011 }; 1012 1013 struct base { 1014 template <std::size_t I, typename V> 1015 inline static constexpr AUTO_REFREF get_alt(V &&v) 1016 AUTO_REFREF_RETURN(recursive_union::get_alt( 1017 data(lib::forward<V>(v)), in_place_index_t<I>{})) 1018 }; 1019 1020 struct variant { 1021 template <std::size_t I, typename V> 1022 inline static constexpr AUTO_REFREF get_alt(V &&v) 1023 AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_)) 1024 }; 1025 1026 } // namespace access 1027 1028 namespace visitation { 1029 1030 struct base { 1031 template <typename T> 1032 inline static constexpr const T &at(const T &elem) { 1033 return elem; 1034 } 1035 1036 template <typename T, std::size_t N, typename... Is> 1037 inline static constexpr const lib::remove_all_extents_t<T> &at( 1038 const lib::array<T, N> &elems, std::size_t i, Is... is) { 1039 return at(elems[i], is...); 1040 } 1041 1042 template <typename F, typename... Fs> 1043 inline static constexpr int visit_visitor_return_type_check() { 1044 static_assert(lib::all<std::is_same<F, Fs>::value...>::value, 1045 "`mpark::visit` requires the visitor to have a single " 1046 "return type."); 1047 return 0; 1048 } 1049 1050 template <typename... Fs> 1051 inline static constexpr lib::array< 1052 lib::common_type_t<lib::decay_t<Fs>...>, 1053 sizeof...(Fs)> 1054 make_farray(Fs &&... fs) { 1055 using result = lib::array<lib::common_type_t<lib::decay_t<Fs>...>, 1056 sizeof...(Fs)>; 1057 return visit_visitor_return_type_check<lib::decay_t<Fs>...>(), 1058 result{{lib::forward<Fs>(fs)...}}; 1059 } 1060 1061 template <std::size_t... Is> 1062 struct dispatcher { 1063 template <typename F, typename... Vs> 1064 struct impl { 1065 inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs) 1066 DECLTYPE_AUTO_RETURN(lib::invoke( 1067 static_cast<F>(f), 1068 access::base::get_alt<Is>(static_cast<Vs>(vs))...)) 1069 }; 1070 }; 1071 1072 template <typename F, typename... Vs, std::size_t... Is> 1073 inline static constexpr AUTO make_dispatch(lib::index_sequence<Is...>) 1074 AUTO_RETURN(&dispatcher<Is...>::template impl<F, Vs...>::dispatch) 1075 1076 template <std::size_t I, typename F, typename... Vs> 1077 inline static constexpr AUTO make_fdiagonal_impl() 1078 AUTO_RETURN(make_dispatch<F, Vs...>( 1079 lib::index_sequence<lib::indexed_type<I, Vs>::value...>{})) 1080 1081 template <typename F, typename... Vs, std::size_t... Is> 1082 inline static constexpr AUTO make_fdiagonal_impl( 1083 lib::index_sequence<Is...>) 1084 AUTO_RETURN(make_farray(make_fdiagonal_impl<Is, F, Vs...>()...)) 1085 1086 template <typename F, typename V, typename... Vs> 1087 inline static constexpr /* auto * */ auto make_fdiagonal() 1088 -> decltype(make_fdiagonal_impl<F, V, Vs...>( 1089 lib::make_index_sequence<lib::decay_t<V>::size()>{})) { 1090 static_assert(lib::all<(lib::decay_t<V>::size() == 1091 lib::decay_t<Vs>::size())...>::value, 1092 "all of the variants must be the same size."); 1093 return make_fdiagonal_impl<F, V, Vs...>( 1094 lib::make_index_sequence<lib::decay_t<V>::size()>{}); 1095 } 1096 1097 #ifdef MPARK_RETURN_TYPE_DEDUCTION 1098 template <typename F, typename... Vs, typename Is> 1099 inline static constexpr auto make_fmatrix_impl(Is is) { 1100 return make_dispatch<F, Vs...>(is); 1101 } 1102 1103 template <typename F, 1104 typename... Vs, 1105 typename Is, 1106 std::size_t... Js, 1107 typename... Ls> 1108 inline static constexpr auto make_fmatrix_impl( 1109 Is, lib::index_sequence<Js...>, Ls... ls) { 1110 return make_farray(make_fmatrix_impl<F, Vs...>( 1111 lib::push_back_t<Is, Js>{}, ls...)...); 1112 } 1113 1114 template <typename F, typename... Vs> 1115 inline static constexpr auto make_fmatrix() { 1116 return make_fmatrix_impl<F, Vs...>( 1117 lib::index_sequence<>{}, 1118 lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...); 1119 } 1120 #else 1121 template <typename F, typename... Vs> 1122 struct make_fmatrix_impl { 1123 template <typename...> 1124 struct impl; 1125 1126 template <typename Is> 1127 struct impl<Is> { 1128 inline constexpr AUTO operator()() const 1129 AUTO_RETURN(make_dispatch<F, Vs...>(Is{})) 1130 }; 1131 1132 template <typename Is, std::size_t... Js, typename... Ls> 1133 struct impl<Is, lib::index_sequence<Js...>, Ls...> { 1134 inline constexpr AUTO operator()() const 1135 AUTO_RETURN( 1136 make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...)) 1137 }; 1138 }; 1139 1140 template <typename F, typename... Vs> 1141 inline static constexpr AUTO make_fmatrix() 1142 AUTO_RETURN( 1143 typename make_fmatrix_impl<F, Vs...>::template impl< 1144 lib::index_sequence<>, 1145 lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}()) 1146 #endif 1147 }; // namespace base 1148 1149 template <typename F, typename... Vs> 1150 using FDiagonal = decltype(base::make_fdiagonal<F, Vs...>()); 1151 1152 template <typename F, typename... Vs> 1153 struct fdiagonal { 1154 #ifdef _MSC_VER 1155 #pragma warning(push) 1156 #pragma warning(disable : 4268) 1157 #endif 1158 static constexpr FDiagonal<F, Vs...> value = 1159 base::make_fdiagonal<F, Vs...>(); 1160 #ifdef _MSC_VER 1161 #pragma warning(pop) 1162 #endif 1163 }; 1164 1165 template <typename F, typename... Vs> 1166 constexpr FDiagonal<F, Vs...> fdiagonal<F, Vs...>::value; 1167 1168 template <typename F, typename... Vs> 1169 using FMatrix = decltype(base::make_fmatrix<F, Vs...>()); 1170 1171 template <typename F, typename... Vs> 1172 struct fmatrix { 1173 #ifdef _MSC_VER 1174 #pragma warning(push) 1175 #pragma warning(disable : 4268) 1176 #endif 1177 static constexpr FMatrix<F, Vs...> value = 1178 base::make_fmatrix<F, Vs...>(); 1179 #ifdef _MSC_VER 1180 #pragma warning(pop) 1181 #endif 1182 }; 1183 1184 template <typename F, typename... Vs> 1185 constexpr FMatrix<F, Vs...> fmatrix<F, Vs...>::value; 1186 1187 struct alt { 1188 template <typename Visitor, typename... Vs> 1189 inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, 1190 Visitor &&visitor, 1191 Vs &&... vs) 1192 DECLTYPE_AUTO_RETURN(base::at( 1193 fdiagonal<Visitor &&, 1194 decltype(as_base(lib::forward<Vs>(vs)))...>::value, 1195 index)(lib::forward<Visitor>(visitor), 1196 as_base(lib::forward<Vs>(vs))...)) 1197 1198 template <typename Visitor, typename... Vs> 1199 inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, 1200 Vs &&... vs) 1201 DECLTYPE_AUTO_RETURN(base::at( 1202 fmatrix<Visitor &&, 1203 decltype(as_base(lib::forward<Vs>(vs)))...>::value, 1204 vs.index()...)(lib::forward<Visitor>(visitor), 1205 as_base(lib::forward<Vs>(vs))...)) 1206 }; 1207 1208 struct variant { 1209 private: 1210 template <typename Visitor, typename... Values> 1211 struct visit_exhaustive_visitor_check { 1212 static_assert( 1213 lib::is_invocable<Visitor, Values...>::value, 1214 "`mpark::visit` requires the visitor to be exhaustive."); 1215 1216 #ifdef _MSC_VER 1217 #pragma warning(push) 1218 #pragma warning(disable : 4100) 1219 #endif 1220 inline constexpr DECLTYPE_AUTO operator()(Visitor &&visitor, 1221 Values &&... values) const 1222 DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor), 1223 lib::forward<Values>(values)...)) 1224 #ifdef _MSC_VER 1225 #pragma warning(pop) 1226 #endif 1227 }; 1228 1229 template <typename Visitor> 1230 struct value_visitor { 1231 Visitor &&visitor_; 1232 1233 template <typename... Alts> 1234 inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const 1235 DECLTYPE_AUTO_RETURN( 1236 visit_exhaustive_visitor_check< 1237 Visitor, 1238 decltype((lib::forward<Alts>(alts).value))...>{}( 1239 lib::forward<Visitor>(visitor_), 1240 lib::forward<Alts>(alts).value...)) 1241 }; 1242 1243 template <typename Visitor> 1244 inline static constexpr AUTO make_value_visitor(Visitor &&visitor) 1245 AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)}) 1246 1247 public: 1248 template <typename Visitor, typename... Vs> 1249 inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, 1250 Visitor &&visitor, 1251 Vs &&... vs) 1252 DECLTYPE_AUTO_RETURN( 1253 alt::visit_alt_at(index, 1254 lib::forward<Visitor>(visitor), 1255 lib::forward<Vs>(vs).impl_...)) 1256 1257 template <typename Visitor, typename... Vs> 1258 inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, 1259 Vs &&... vs) 1260 DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor), 1261 lib::forward<Vs>(vs).impl_...)) 1262 1263 template <typename Visitor, typename... Vs> 1264 inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, 1265 Visitor &&visitor, 1266 Vs &&... vs) 1267 DECLTYPE_AUTO_RETURN( 1268 visit_alt_at(index, 1269 make_value_visitor(lib::forward<Visitor>(visitor)), 1270 lib::forward<Vs>(vs)...)) 1271 1272 template <typename Visitor, typename... Vs> 1273 inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, 1274 Vs &&... vs) 1275 DECLTYPE_AUTO_RETURN( 1276 visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)), 1277 lib::forward<Vs>(vs)...)) 1278 }; 1279 1280 } // namespace visitation 1281 1282 template <std::size_t Index, typename T> 1283 struct alt { 1284 using value_type = T; 1285 1286 #ifdef _MSC_VER 1287 #pragma warning(push) 1288 #pragma warning(disable : 4244) 1289 #endif 1290 template <typename... Args> 1291 inline explicit constexpr alt(in_place_t, Args &&... args) 1292 : value(lib::forward<Args>(args)...) {} 1293 #ifdef _MSC_VER 1294 #pragma warning(pop) 1295 #endif 1296 1297 T value; 1298 }; 1299 1300 template <Trait DestructibleTrait, std::size_t Index, typename... Ts> 1301 union recursive_union; 1302 1303 template <Trait DestructibleTrait, std::size_t Index> 1304 union recursive_union<DestructibleTrait, Index> {}; 1305 1306 #define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ 1307 template <std::size_t Index, typename T, typename... Ts> \ 1308 union recursive_union<destructible_trait, Index, T, Ts...> { \ 1309 public: \ 1310 inline explicit constexpr recursive_union(valueless_t) noexcept \ 1311 : dummy_{} {} \ 1312 \ 1313 template <typename... Args> \ 1314 inline explicit constexpr recursive_union(in_place_index_t<0>, \ 1315 Args &&... args) \ 1316 : head_(in_place_t{}, lib::forward<Args>(args)...) {} \ 1317 \ 1318 template <std::size_t I, typename... Args> \ 1319 inline explicit constexpr recursive_union(in_place_index_t<I>, \ 1320 Args &&... args) \ 1321 : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \ 1322 \ 1323 recursive_union(const recursive_union &) = default; \ 1324 recursive_union(recursive_union &&) = default; \ 1325 \ 1326 destructor \ 1327 \ 1328 recursive_union &operator=(const recursive_union &) = default; \ 1329 recursive_union &operator=(recursive_union &&) = default; \ 1330 \ 1331 private: \ 1332 char dummy_; \ 1333 alt<Index, T> head_; \ 1334 recursive_union<destructible_trait, Index + 1, Ts...> tail_; \ 1335 \ 1336 friend struct access::recursive_union; \ 1337 } 1338 1339 MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, 1340 ~recursive_union() = default;); 1341 MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, 1342 ~recursive_union() {}); 1343 MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, 1344 ~recursive_union() = delete;); 1345 1346 #undef MPARK_VARIANT_RECURSIVE_UNION 1347 1348 using index_t = unsigned int; 1349 1350 template <Trait DestructibleTrait, typename... Ts> 1351 class base { 1352 public: 1353 inline explicit constexpr base(valueless_t tag) noexcept 1354 : data_(tag), index_(static_cast<index_t>(-1)) {} 1355 1356 template <std::size_t I, typename... Args> 1357 inline explicit constexpr base(in_place_index_t<I>, Args &&... args) 1358 : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...), 1359 index_(I) {} 1360 1361 inline constexpr bool valueless_by_exception() const noexcept { 1362 return index_ == static_cast<index_t>(-1); 1363 } 1364 1365 inline constexpr std::size_t index() const noexcept { 1366 return valueless_by_exception() ? variant_npos : index_; 1367 } 1368 1369 protected: 1370 using data_t = recursive_union<DestructibleTrait, 0, Ts...>; 1371 1372 friend inline constexpr base &as_base(base &b) { return b; } 1373 friend inline constexpr const base &as_base(const base &b) { return b; } 1374 friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } 1375 friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } 1376 1377 friend inline constexpr data_t &data(base &b) { return b.data_; } 1378 friend inline constexpr const data_t &data(const base &b) { return b.data_; } 1379 friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } 1380 friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } 1381 1382 inline static constexpr std::size_t size() { return sizeof...(Ts); } 1383 1384 data_t data_; 1385 index_t index_; 1386 1387 friend struct access::base; 1388 friend struct visitation::base; 1389 }; 1390 1391 struct dtor { 1392 #ifdef _MSC_VER 1393 #pragma warning(push) 1394 #pragma warning(disable : 4100) 1395 #endif 1396 template <typename Alt> 1397 inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } 1398 #ifdef _MSC_VER 1399 #pragma warning(pop) 1400 #endif 1401 }; 1402 1403 #if defined(_MSC_VER) && _MSC_VER < 1910 1404 #define INHERITING_CTOR(type, base) \ 1405 template <typename... Args> \ 1406 inline explicit constexpr type(Args &&... args) \ 1407 : base(lib::forward<Args>(args)...) {} 1408 #else 1409 #define INHERITING_CTOR(type, base) using base::base; 1410 #endif 1411 1412 template <typename Traits, Trait = Traits::destructible_trait> 1413 class destructor; 1414 1415 #define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ 1416 template <typename... Ts> \ 1417 class destructor<traits<Ts...>, destructible_trait> \ 1418 : public base<destructible_trait, Ts...> { \ 1419 using super = base<destructible_trait, Ts...>; \ 1420 \ 1421 public: \ 1422 INHERITING_CTOR(destructor, super) \ 1423 using super::operator=; \ 1424 \ 1425 destructor(const destructor &) = default; \ 1426 destructor(destructor &&) = default; \ 1427 definition \ 1428 destructor &operator=(const destructor &) = default; \ 1429 destructor &operator=(destructor &&) = default; \ 1430 \ 1431 protected: \ 1432 destroy \ 1433 } 1434 1435 MPARK_VARIANT_DESTRUCTOR( 1436 Trait::TriviallyAvailable, 1437 ~destructor() = default;, 1438 inline void destroy() noexcept { 1439 this->index_ = static_cast<index_t>(-1); 1440 }); 1441 1442 MPARK_VARIANT_DESTRUCTOR( 1443 Trait::Available, 1444 ~destructor() { destroy(); }, 1445 inline void destroy() noexcept { 1446 if (!this->valueless_by_exception()) { 1447 visitation::alt::visit_alt(dtor{}, *this); 1448 } 1449 this->index_ = static_cast<index_t>(-1); 1450 }); 1451 1452 MPARK_VARIANT_DESTRUCTOR( 1453 Trait::Unavailable, 1454 ~destructor() = delete;, 1455 inline void destroy() noexcept = delete;); 1456 1457 #undef MPARK_VARIANT_DESTRUCTOR 1458 1459 template <typename Traits> 1460 class constructor : public destructor<Traits> { 1461 using super = destructor<Traits>; 1462 1463 public: 1464 INHERITING_CTOR(constructor, super) 1465 using super::operator=; 1466 1467 protected: 1468 #ifndef MPARK_GENERIC_LAMBDAS 1469 struct ctor { 1470 template <typename LhsAlt, typename RhsAlt> 1471 inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { 1472 constructor::construct_alt(lhs_alt, 1473 lib::forward<RhsAlt>(rhs_alt).value); 1474 } 1475 }; 1476 #endif 1477 1478 template <std::size_t I, typename T, typename... Args> 1479 inline static T &construct_alt(alt<I, T> &a, Args &&... args) { 1480 ::new (static_cast<void *>(lib::addressof(a))) 1481 alt<I, T>(in_place_t{}, lib::forward<Args>(args)...); 1482 return a.value; 1483 } 1484 1485 template <typename Rhs> 1486 inline static void generic_construct(constructor &lhs, Rhs &&rhs) { 1487 lhs.destroy(); 1488 if (!rhs.valueless_by_exception()) { 1489 visitation::alt::visit_alt_at( 1490 rhs.index(), 1491 #ifdef MPARK_GENERIC_LAMBDAS 1492 [](auto &lhs_alt, auto &&rhs_alt) { 1493 constructor::construct_alt( 1494 lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value); 1495 } 1496 #else 1497 ctor{} 1498 #endif 1499 , 1500 lhs, 1501 lib::forward<Rhs>(rhs)); 1502 lhs.index_ = rhs.index_; 1503 } 1504 } 1505 }; 1506 1507 template <typename Traits, Trait = Traits::move_constructible_trait> 1508 class move_constructor; 1509 1510 #define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ 1511 template <typename... Ts> \ 1512 class move_constructor<traits<Ts...>, move_constructible_trait> \ 1513 : public constructor<traits<Ts...>> { \ 1514 using super = constructor<traits<Ts...>>; \ 1515 \ 1516 public: \ 1517 INHERITING_CTOR(move_constructor, super) \ 1518 using super::operator=; \ 1519 \ 1520 move_constructor(const move_constructor &) = default; \ 1521 definition \ 1522 ~move_constructor() = default; \ 1523 move_constructor &operator=(const move_constructor &) = default; \ 1524 move_constructor &operator=(move_constructor &&) = default; \ 1525 } 1526 1527 MPARK_VARIANT_MOVE_CONSTRUCTOR( 1528 Trait::TriviallyAvailable, 1529 move_constructor(move_constructor &&that) = default;); 1530 1531 MPARK_VARIANT_MOVE_CONSTRUCTOR( 1532 Trait::Available, 1533 move_constructor(move_constructor &&that) noexcept( 1534 lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value) 1535 : move_constructor(valueless_t{}) { 1536 this->generic_construct(*this, lib::move(that)); 1537 }); 1538 1539 MPARK_VARIANT_MOVE_CONSTRUCTOR( 1540 Trait::Unavailable, 1541 move_constructor(move_constructor &&) = delete;); 1542 1543 #undef MPARK_VARIANT_MOVE_CONSTRUCTOR 1544 1545 template <typename Traits, Trait = Traits::copy_constructible_trait> 1546 class copy_constructor; 1547 1548 #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ 1549 template <typename... Ts> \ 1550 class copy_constructor<traits<Ts...>, copy_constructible_trait> \ 1551 : public move_constructor<traits<Ts...>> { \ 1552 using super = move_constructor<traits<Ts...>>; \ 1553 \ 1554 public: \ 1555 INHERITING_CTOR(copy_constructor, super) \ 1556 using super::operator=; \ 1557 \ 1558 definition \ 1559 copy_constructor(copy_constructor &&) = default; \ 1560 ~copy_constructor() = default; \ 1561 copy_constructor &operator=(const copy_constructor &) = default; \ 1562 copy_constructor &operator=(copy_constructor &&) = default; \ 1563 } 1564 1565 MPARK_VARIANT_COPY_CONSTRUCTOR( 1566 Trait::TriviallyAvailable, 1567 copy_constructor(const copy_constructor &that) = default;); 1568 1569 MPARK_VARIANT_COPY_CONSTRUCTOR( 1570 Trait::Available, 1571 copy_constructor(const copy_constructor &that) 1572 : copy_constructor(valueless_t{}) { 1573 this->generic_construct(*this, that); 1574 }); 1575 1576 MPARK_VARIANT_COPY_CONSTRUCTOR( 1577 Trait::Unavailable, 1578 copy_constructor(const copy_constructor &) = delete;); 1579 1580 #undef MPARK_VARIANT_COPY_CONSTRUCTOR 1581 1582 template <typename Traits> 1583 class assignment : public copy_constructor<Traits> { 1584 using super = copy_constructor<Traits>; 1585 1586 public: 1587 INHERITING_CTOR(assignment, super) 1588 using super::operator=; 1589 1590 template <std::size_t I, typename... Args> 1591 inline /* auto & */ auto emplace(Args &&... args) 1592 -> decltype(this->construct_alt(access::base::get_alt<I>(*this), 1593 lib::forward<Args>(args)...)) { 1594 this->destroy(); 1595 auto &result = this->construct_alt(access::base::get_alt<I>(*this), 1596 lib::forward<Args>(args)...); 1597 this->index_ = I; 1598 return result; 1599 } 1600 1601 protected: 1602 #ifndef MPARK_GENERIC_LAMBDAS 1603 template <typename That> 1604 struct assigner { 1605 template <typename ThisAlt, typename ThatAlt> 1606 inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { 1607 self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value); 1608 } 1609 assignment *self; 1610 }; 1611 #endif 1612 1613 template <std::size_t I, typename T, typename Arg> 1614 inline void assign_alt(alt<I, T> &a, Arg &&arg) { 1615 if (this->index() == I) { 1616 #ifdef _MSC_VER 1617 #pragma warning(push) 1618 #pragma warning(disable : 4244) 1619 #endif 1620 a.value = lib::forward<Arg>(arg); 1621 #ifdef _MSC_VER 1622 #pragma warning(pop) 1623 #endif 1624 } else { 1625 struct { 1626 void operator()(std::true_type) const { 1627 this_->emplace<I>(lib::forward<Arg>(arg_)); 1628 } 1629 void operator()(std::false_type) const { 1630 this_->emplace<I>(T(lib::forward<Arg>(arg_))); 1631 } 1632 assignment *this_; 1633 Arg &&arg_; 1634 } impl{this, lib::forward<Arg>(arg)}; 1635 impl(lib::bool_constant< 1636 std::is_nothrow_constructible<T, Arg>::value || 1637 !std::is_nothrow_move_constructible<T>::value>{}); 1638 } 1639 } 1640 1641 template <typename That> 1642 inline void generic_assign(That &&that) { 1643 if (this->valueless_by_exception() && that.valueless_by_exception()) { 1644 // do nothing. 1645 } else if (that.valueless_by_exception()) { 1646 this->destroy(); 1647 } else { 1648 visitation::alt::visit_alt_at( 1649 that.index(), 1650 #ifdef MPARK_GENERIC_LAMBDAS 1651 [this](auto &this_alt, auto &&that_alt) { 1652 this->assign_alt( 1653 this_alt, lib::forward<decltype(that_alt)>(that_alt).value); 1654 } 1655 #else 1656 assigner<That>{this} 1657 #endif 1658 , 1659 *this, 1660 lib::forward<That>(that)); 1661 } 1662 } 1663 }; 1664 1665 template <typename Traits, Trait = Traits::move_assignable_trait> 1666 class move_assignment; 1667 1668 #define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ 1669 template <typename... Ts> \ 1670 class move_assignment<traits<Ts...>, move_assignable_trait> \ 1671 : public assignment<traits<Ts...>> { \ 1672 using super = assignment<traits<Ts...>>; \ 1673 \ 1674 public: \ 1675 INHERITING_CTOR(move_assignment, super) \ 1676 using super::operator=; \ 1677 \ 1678 move_assignment(const move_assignment &) = default; \ 1679 move_assignment(move_assignment &&) = default; \ 1680 ~move_assignment() = default; \ 1681 move_assignment &operator=(const move_assignment &) = default; \ 1682 definition \ 1683 } 1684 1685 MPARK_VARIANT_MOVE_ASSIGNMENT( 1686 Trait::TriviallyAvailable, 1687 move_assignment &operator=(move_assignment &&that) = default;); 1688 1689 MPARK_VARIANT_MOVE_ASSIGNMENT( 1690 Trait::Available, 1691 move_assignment & 1692 operator=(move_assignment &&that) noexcept( 1693 lib::all<(std::is_nothrow_move_constructible<Ts>::value && 1694 std::is_nothrow_move_assignable<Ts>::value)...>::value) { 1695 this->generic_assign(lib::move(that)); 1696 return *this; 1697 }); 1698 1699 MPARK_VARIANT_MOVE_ASSIGNMENT( 1700 Trait::Unavailable, 1701 move_assignment &operator=(move_assignment &&) = delete;); 1702 1703 #undef MPARK_VARIANT_MOVE_ASSIGNMENT 1704 1705 template <typename Traits, Trait = Traits::copy_assignable_trait> 1706 class copy_assignment; 1707 1708 #define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ 1709 template <typename... Ts> \ 1710 class copy_assignment<traits<Ts...>, copy_assignable_trait> \ 1711 : public move_assignment<traits<Ts...>> { \ 1712 using super = move_assignment<traits<Ts...>>; \ 1713 \ 1714 public: \ 1715 INHERITING_CTOR(copy_assignment, super) \ 1716 using super::operator=; \ 1717 \ 1718 copy_assignment(const copy_assignment &) = default; \ 1719 copy_assignment(copy_assignment &&) = default; \ 1720 ~copy_assignment() = default; \ 1721 definition \ 1722 copy_assignment &operator=(copy_assignment &&) = default; \ 1723 } 1724 1725 MPARK_VARIANT_COPY_ASSIGNMENT( 1726 Trait::TriviallyAvailable, 1727 copy_assignment &operator=(const copy_assignment &that) = default;); 1728 1729 MPARK_VARIANT_COPY_ASSIGNMENT( 1730 Trait::Available, 1731 copy_assignment &operator=(const copy_assignment &that) { 1732 this->generic_assign(that); 1733 return *this; 1734 }); 1735 1736 MPARK_VARIANT_COPY_ASSIGNMENT( 1737 Trait::Unavailable, 1738 copy_assignment &operator=(const copy_assignment &) = delete;); 1739 1740 #undef MPARK_VARIANT_COPY_ASSIGNMENT 1741 1742 template <typename... Ts> 1743 class impl : public copy_assignment<traits<Ts...>> { 1744 using super = copy_assignment<traits<Ts...>>; 1745 1746 public: 1747 INHERITING_CTOR(impl, super) 1748 using super::operator=; 1749 1750 template <std::size_t I, typename Arg> 1751 inline void assign(Arg &&arg) { 1752 this->assign_alt(access::base::get_alt<I>(*this), 1753 lib::forward<Arg>(arg)); 1754 } 1755 1756 inline void swap(impl &that) { 1757 if (this->valueless_by_exception() && that.valueless_by_exception()) { 1758 // do nothing. 1759 } else if (this->index() == that.index()) { 1760 visitation::alt::visit_alt_at(this->index(), 1761 #ifdef MPARK_GENERIC_LAMBDAS 1762 [](auto &this_alt, auto &that_alt) { 1763 using std::swap; 1764 swap(this_alt.value, 1765 that_alt.value); 1766 } 1767 #else 1768 swapper{} 1769 #endif 1770 , 1771 *this, 1772 that); 1773 } else { 1774 impl *lhs = this; 1775 impl *rhs = lib::addressof(that); 1776 if (lhs->move_nothrow() && !rhs->move_nothrow()) { 1777 std::swap(lhs, rhs); 1778 } 1779 impl tmp(lib::move(*rhs)); 1780 #ifdef MPARK_EXCEPTIONS 1781 // EXTENSION: When the move construction of `lhs` into `rhs` throws 1782 // and `tmp` is nothrow move constructible then we move `tmp` back 1783 // into `rhs` and provide the strong exception safety guarantee. 1784 try { 1785 this->generic_construct(*rhs, lib::move(*lhs)); 1786 } catch (...) { 1787 if (tmp.move_nothrow()) { 1788 this->generic_construct(*rhs, lib::move(tmp)); 1789 } 1790 throw; 1791 } 1792 #else 1793 this->generic_construct(*rhs, lib::move(*lhs)); 1794 #endif 1795 this->generic_construct(*lhs, lib::move(tmp)); 1796 } 1797 } 1798 1799 private: 1800 #ifndef MPARK_GENERIC_LAMBDAS 1801 struct swapper { 1802 template <typename ThisAlt, typename ThatAlt> 1803 inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { 1804 using std::swap; 1805 swap(this_alt.value, that_alt.value); 1806 } 1807 }; 1808 #endif 1809 1810 inline constexpr bool move_nothrow() const { 1811 return this->valueless_by_exception() || 1812 lib::array<bool, sizeof...(Ts)>{ 1813 {std::is_nothrow_move_constructible<Ts>::value...} 1814 }[this->index()]; 1815 } 1816 }; 1817 1818 template <std::size_t I, typename T> 1819 struct overload_leaf { 1820 using F = lib::size_constant<I> (*)(T); 1821 operator F() const { return nullptr; } 1822 }; 1823 1824 template <typename... Ts> 1825 struct overload_impl { 1826 private: 1827 template <typename> 1828 struct impl; 1829 1830 template <std::size_t... Is> 1831 struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>... {}; 1832 1833 public: 1834 using type = impl<lib::index_sequence_for<Ts...>>; 1835 }; 1836 1837 template <typename... Ts> 1838 using overload = typename overload_impl<Ts...>::type; 1839 1840 template <typename T, typename... Ts> 1841 using best_match = lib::invoke_result_t<overload<Ts...>, T &&>; 1842 1843 template <typename T> 1844 struct is_in_place_index : std::false_type {}; 1845 1846 template <std::size_t I> 1847 struct is_in_place_index<in_place_index_t<I>> : std::true_type {}; 1848 1849 template <typename T> 1850 struct is_in_place_type : std::false_type {}; 1851 1852 template <typename T> 1853 struct is_in_place_type<in_place_type_t<T>> : std::true_type {}; 1854 1855 } // detail 1856 1857 template <typename... Ts> 1858 class variant { 1859 static_assert(0 < sizeof...(Ts), 1860 "variant must consist of at least one alternative."); 1861 1862 static_assert(lib::all<!std::is_array<Ts>::value...>::value, 1863 "variant can not have an array type as an alternative."); 1864 1865 static_assert(lib::all<!std::is_reference<Ts>::value...>::value, 1866 "variant can not have a reference type as an alternative."); 1867 1868 static_assert(lib::all<!std::is_void<Ts>::value...>::value, 1869 "variant can not have a void type as an alternative."); 1870 1871 public: 1872 template < 1873 typename Front = lib::type_pack_element_t<0, Ts...>, 1874 lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0> 1875 inline constexpr variant() noexcept( 1876 std::is_nothrow_default_constructible<Front>::value) 1877 : impl_(in_place_index_t<0>{}) {} 1878 1879 variant(const variant &) = default; 1880 variant(variant &&) = default; 1881 1882 template < 1883 typename Arg, 1884 typename Decayed = lib::decay_t<Arg>, 1885 lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0, 1886 lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0, 1887 lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0, 1888 std::size_t I = detail::best_match<Arg, Ts...>::value, 1889 typename T = lib::type_pack_element_t<I, Ts...>, 1890 lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0> 1891 inline constexpr variant(Arg &&arg) noexcept( 1892 std::is_nothrow_constructible<T, Arg>::value) 1893 : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg)) {} 1894 1895 template < 1896 std::size_t I, 1897 typename... Args, 1898 typename T = lib::type_pack_element_t<I, Ts...>, 1899 lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> 1900 inline explicit constexpr variant( 1901 in_place_index_t<I>, 1902 Args &&... args) noexcept(std::is_nothrow_constructible<T, 1903 Args...>::value) 1904 : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {} 1905 1906 template < 1907 std::size_t I, 1908 typename Up, 1909 typename... Args, 1910 typename T = lib::type_pack_element_t<I, Ts...>, 1911 lib::enable_if_t<std::is_constructible<T, 1912 std::initializer_list<Up> &, 1913 Args...>::value, 1914 int> = 0> 1915 inline explicit constexpr variant( 1916 in_place_index_t<I>, 1917 std::initializer_list<Up> il, 1918 Args &&... args) noexcept(std:: 1919 is_nothrow_constructible< 1920 T, 1921 std::initializer_list<Up> &, 1922 Args...>::value) 1923 : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {} 1924 1925 template < 1926 typename T, 1927 typename... Args, 1928 std::size_t I = detail::find_index_sfinae<T, Ts...>::value, 1929 lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> 1930 inline explicit constexpr variant( 1931 in_place_type_t<T>, 1932 Args &&... args) noexcept(std::is_nothrow_constructible<T, 1933 Args...>::value) 1934 : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {} 1935 1936 template < 1937 typename T, 1938 typename Up, 1939 typename... Args, 1940 std::size_t I = detail::find_index_sfinae<T, Ts...>::value, 1941 lib::enable_if_t<std::is_constructible<T, 1942 std::initializer_list<Up> &, 1943 Args...>::value, 1944 int> = 0> 1945 inline explicit constexpr variant( 1946 in_place_type_t<T>, 1947 std::initializer_list<Up> il, 1948 Args &&... args) noexcept(std:: 1949 is_nothrow_constructible< 1950 T, 1951 std::initializer_list<Up> &, 1952 Args...>::value) 1953 : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {} 1954 1955 ~variant() = default; 1956 1957 variant &operator=(const variant &) = default; 1958 variant &operator=(variant &&) = default; 1959 1960 template <typename Arg, 1961 lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value, 1962 int> = 0, 1963 std::size_t I = detail::best_match<Arg, Ts...>::value, 1964 typename T = lib::type_pack_element_t<I, Ts...>, 1965 lib::enable_if_t<(std::is_assignable<T &, Arg>::value && 1966 std::is_constructible<T, Arg>::value), 1967 int> = 0> 1968 inline variant &operator=(Arg &&arg) noexcept( 1969 (std::is_nothrow_assignable<T &, Arg>::value && 1970 std::is_nothrow_constructible<T, Arg>::value)) { 1971 impl_.template assign<I>(lib::forward<Arg>(arg)); 1972 return *this; 1973 } 1974 1975 template < 1976 std::size_t I, 1977 typename... Args, 1978 typename T = lib::type_pack_element_t<I, Ts...>, 1979 lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> 1980 inline T &emplace(Args &&... args) { 1981 return impl_.template emplace<I>(lib::forward<Args>(args)...); 1982 } 1983 1984 template < 1985 std::size_t I, 1986 typename Up, 1987 typename... Args, 1988 typename T = lib::type_pack_element_t<I, Ts...>, 1989 lib::enable_if_t<std::is_constructible<T, 1990 std::initializer_list<Up> &, 1991 Args...>::value, 1992 int> = 0> 1993 inline T &emplace(std::initializer_list<Up> il, Args &&... args) { 1994 return impl_.template emplace<I>(il, lib::forward<Args>(args)...); 1995 } 1996 1997 template < 1998 typename T, 1999 typename... Args, 2000 std::size_t I = detail::find_index_sfinae<T, Ts...>::value, 2001 lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> 2002 inline T &emplace(Args &&... args) { 2003 return impl_.template emplace<I>(lib::forward<Args>(args)...); 2004 } 2005 2006 template < 2007 typename T, 2008 typename Up, 2009 typename... Args, 2010 std::size_t I = detail::find_index_sfinae<T, Ts...>::value, 2011 lib::enable_if_t<std::is_constructible<T, 2012 std::initializer_list<Up> &, 2013 Args...>::value, 2014 int> = 0> 2015 inline T &emplace(std::initializer_list<Up> il, Args &&... args) { 2016 return impl_.template emplace<I>(il, lib::forward<Args>(args)...); 2017 } 2018 2019 inline constexpr bool valueless_by_exception() const noexcept { 2020 return impl_.valueless_by_exception(); 2021 } 2022 2023 inline constexpr std::size_t index() const noexcept { 2024 return impl_.index(); 2025 } 2026 2027 template <bool Dummy = true, 2028 lib::enable_if_t< 2029 lib::all<Dummy, 2030 (lib::dependent_type<std::is_move_constructible<Ts>, 2031 Dummy>::value && 2032 lib::dependent_type<lib::is_swappable<Ts>, 2033 Dummy>::value)...>::value, 2034 int> = 0> 2035 inline void swap(variant &that) noexcept( 2036 lib::all<(std::is_nothrow_move_constructible<Ts>::value && 2037 lib::is_nothrow_swappable<Ts>::value)...>::value) { 2038 impl_.swap(that.impl_); 2039 } 2040 2041 private: 2042 detail::impl<Ts...> impl_; 2043 2044 friend struct detail::access::variant; 2045 friend struct detail::visitation::variant; 2046 }; 2047 2048 template <std::size_t I, typename... Ts> 2049 inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept { 2050 return v.index() == I; 2051 } 2052 2053 template <typename T, typename... Ts> 2054 inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept { 2055 return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v); 2056 } 2057 2058 namespace detail { 2059 template <std::size_t I, typename V> 2060 struct generic_get_impl { 2061 constexpr generic_get_impl(int) {} 2062 2063 constexpr AUTO_REFREF operator()(V &&v) const 2064 AUTO_REFREF_RETURN( 2065 access::variant::get_alt<I>(lib::forward<V>(v)).value) 2066 }; 2067 2068 template <std::size_t I, typename V> 2069 inline constexpr AUTO_REFREF generic_get(V &&v) 2070 AUTO_REFREF_RETURN(generic_get_impl<I, V>( 2071 holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))( 2072 lib::forward<V>(v))) 2073 } // namespace detail 2074 2075 template <std::size_t I, typename... Ts> 2076 inline constexpr variant_alternative_t<I, variant<Ts...>> &get( 2077 variant<Ts...> &v) { 2078 return detail::generic_get<I>(v); 2079 } 2080 2081 template <std::size_t I, typename... Ts> 2082 inline constexpr variant_alternative_t<I, variant<Ts...>> &&get( 2083 variant<Ts...> &&v) { 2084 return detail::generic_get<I>(lib::move(v)); 2085 } 2086 2087 template <std::size_t I, typename... Ts> 2088 inline constexpr const variant_alternative_t<I, variant<Ts...>> &get( 2089 const variant<Ts...> &v) { 2090 return detail::generic_get<I>(v); 2091 } 2092 2093 template <std::size_t I, typename... Ts> 2094 inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get( 2095 const variant<Ts...> &&v) { 2096 return detail::generic_get<I>(lib::move(v)); 2097 } 2098 2099 template <typename T, typename... Ts> 2100 inline constexpr T &get(variant<Ts...> &v) { 2101 return get<detail::find_index_checked<T, Ts...>::value>(v); 2102 } 2103 2104 template <typename T, typename... Ts> 2105 inline constexpr T &&get(variant<Ts...> &&v) { 2106 return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v)); 2107 } 2108 2109 template <typename T, typename... Ts> 2110 inline constexpr const T &get(const variant<Ts...> &v) { 2111 return get<detail::find_index_checked<T, Ts...>::value>(v); 2112 } 2113 2114 template <typename T, typename... Ts> 2115 inline constexpr const T &&get(const variant<Ts...> &&v) { 2116 return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v)); 2117 } 2118 2119 namespace detail { 2120 2121 template <std::size_t I, typename V> 2122 inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept 2123 AUTO_RETURN(v && holds_alternative<I>(*v) 2124 ? lib::addressof(access::variant::get_alt<I>(*v).value) 2125 : nullptr) 2126 2127 } // namespace detail 2128 2129 template <std::size_t I, typename... Ts> 2130 inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>> 2131 get_if(variant<Ts...> *v) noexcept { 2132 return detail::generic_get_if<I>(v); 2133 } 2134 2135 template <std::size_t I, typename... Ts> 2136 inline constexpr lib::add_pointer_t< 2137 const variant_alternative_t<I, variant<Ts...>>> 2138 get_if(const variant<Ts...> *v) noexcept { 2139 return detail::generic_get_if<I>(v); 2140 } 2141 2142 template <typename T, typename... Ts> 2143 inline constexpr lib::add_pointer_t<T> 2144 get_if(variant<Ts...> *v) noexcept { 2145 return get_if<detail::find_index_checked<T, Ts...>::value>(v); 2146 } 2147 2148 template <typename T, typename... Ts> 2149 inline constexpr lib::add_pointer_t<const T> 2150 get_if(const variant<Ts...> *v) noexcept { 2151 return get_if<detail::find_index_checked<T, Ts...>::value>(v); 2152 } 2153 2154 template <typename... Ts> 2155 inline constexpr bool operator==(const variant<Ts...> &lhs, 2156 const variant<Ts...> &rhs) { 2157 using detail::visitation::variant; 2158 using lib::equal_to; 2159 #ifdef MPARK_CPP14_CONSTEXPR 2160 if (lhs.index() != rhs.index()) return false; 2161 if (lhs.valueless_by_exception()) return true; 2162 return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); 2163 #else 2164 return lhs.index() == rhs.index() && 2165 (lhs.valueless_by_exception() || 2166 variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); 2167 #endif 2168 } 2169 2170 template <typename... Ts> 2171 inline constexpr bool operator!=(const variant<Ts...> &lhs, 2172 const variant<Ts...> &rhs) { 2173 using detail::visitation::variant; 2174 using lib::not_equal_to; 2175 #ifdef MPARK_CPP14_CONSTEXPR 2176 if (lhs.index() != rhs.index()) return true; 2177 if (lhs.valueless_by_exception()) return false; 2178 return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); 2179 #else 2180 return lhs.index() != rhs.index() || 2181 (!lhs.valueless_by_exception() && 2182 variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); 2183 #endif 2184 } 2185 2186 template <typename... Ts> 2187 inline constexpr bool operator<(const variant<Ts...> &lhs, 2188 const variant<Ts...> &rhs) { 2189 using detail::visitation::variant; 2190 using lib::less; 2191 #ifdef MPARK_CPP14_CONSTEXPR 2192 if (rhs.valueless_by_exception()) return false; 2193 if (lhs.valueless_by_exception()) return true; 2194 if (lhs.index() < rhs.index()) return true; 2195 if (lhs.index() > rhs.index()) return false; 2196 return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); 2197 #else 2198 return !rhs.valueless_by_exception() && 2199 (lhs.valueless_by_exception() || lhs.index() < rhs.index() || 2200 (lhs.index() == rhs.index() && 2201 variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); 2202 #endif 2203 } 2204 2205 template <typename... Ts> 2206 inline constexpr bool operator>(const variant<Ts...> &lhs, 2207 const variant<Ts...> &rhs) { 2208 using detail::visitation::variant; 2209 using lib::greater; 2210 #ifdef MPARK_CPP14_CONSTEXPR 2211 if (lhs.valueless_by_exception()) return false; 2212 if (rhs.valueless_by_exception()) return true; 2213 if (lhs.index() > rhs.index()) return true; 2214 if (lhs.index() < rhs.index()) return false; 2215 return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); 2216 #else 2217 return !lhs.valueless_by_exception() && 2218 (rhs.valueless_by_exception() || lhs.index() > rhs.index() || 2219 (lhs.index() == rhs.index() && 2220 variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); 2221 #endif 2222 } 2223 2224 template <typename... Ts> 2225 inline constexpr bool operator<=(const variant<Ts...> &lhs, 2226 const variant<Ts...> &rhs) { 2227 using detail::visitation::variant; 2228 using lib::less_equal; 2229 #ifdef MPARK_CPP14_CONSTEXPR 2230 if (lhs.valueless_by_exception()) return true; 2231 if (rhs.valueless_by_exception()) return false; 2232 if (lhs.index() < rhs.index()) return true; 2233 if (lhs.index() > rhs.index()) return false; 2234 return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); 2235 #else 2236 return lhs.valueless_by_exception() || 2237 (!rhs.valueless_by_exception() && 2238 (lhs.index() < rhs.index() || 2239 (lhs.index() == rhs.index() && 2240 variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); 2241 #endif 2242 } 2243 2244 template <typename... Ts> 2245 inline constexpr bool operator>=(const variant<Ts...> &lhs, 2246 const variant<Ts...> &rhs) { 2247 using detail::visitation::variant; 2248 using lib::greater_equal; 2249 #ifdef MPARK_CPP14_CONSTEXPR 2250 if (rhs.valueless_by_exception()) return true; 2251 if (lhs.valueless_by_exception()) return false; 2252 if (lhs.index() > rhs.index()) return true; 2253 if (lhs.index() < rhs.index()) return false; 2254 return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); 2255 #else 2256 return rhs.valueless_by_exception() || 2257 (!lhs.valueless_by_exception() && 2258 (lhs.index() > rhs.index() || 2259 (lhs.index() == rhs.index() && 2260 variant::visit_value_at( 2261 lhs.index(), greater_equal{}, lhs, rhs)))); 2262 #endif 2263 } 2264 2265 struct monostate {}; 2266 2267 inline constexpr bool operator<(monostate, monostate) noexcept { 2268 return false; 2269 } 2270 2271 inline constexpr bool operator>(monostate, monostate) noexcept { 2272 return false; 2273 } 2274 2275 inline constexpr bool operator<=(monostate, monostate) noexcept { 2276 return true; 2277 } 2278 2279 inline constexpr bool operator>=(monostate, monostate) noexcept { 2280 return true; 2281 } 2282 2283 inline constexpr bool operator==(monostate, monostate) noexcept { 2284 return true; 2285 } 2286 2287 inline constexpr bool operator!=(monostate, monostate) noexcept { 2288 return false; 2289 } 2290 2291 #ifdef MPARK_CPP14_CONSTEXPR 2292 namespace detail { 2293 2294 inline constexpr bool all(std::initializer_list<bool> bs) { 2295 for (bool b : bs) { 2296 if (!b) { 2297 return false; 2298 } 2299 } 2300 return true; 2301 } 2302 2303 } // namespace detail 2304 2305 template <typename Visitor, typename... Vs> 2306 inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) { 2307 return (detail::all({!vs.valueless_by_exception()...}) 2308 ? (void)0 2309 : throw_bad_variant_access()), 2310 detail::visitation::variant::visit_value( 2311 lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...); 2312 } 2313 #else 2314 namespace detail { 2315 2316 template <std::size_t N> 2317 inline constexpr bool all_impl(const lib::array<bool, N> &bs, 2318 std::size_t idx) { 2319 return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); 2320 } 2321 2322 template <std::size_t N> 2323 inline constexpr bool all(const lib::array<bool, N> &bs) { 2324 return all_impl(bs, 0); 2325 } 2326 2327 } // namespace detail 2328 2329 template <typename Visitor, typename... Vs> 2330 inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) 2331 DECLTYPE_AUTO_RETURN( 2332 (detail::all( 2333 lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}}) 2334 ? (void)0 2335 : throw_bad_variant_access()), 2336 detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor), 2337 lib::forward<Vs>(vs)...)) 2338 #endif 2339 2340 template <typename... Ts> 2341 inline auto swap(variant<Ts...> &lhs, 2342 variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs))) 2343 -> decltype(lhs.swap(rhs)) { 2344 lhs.swap(rhs); 2345 } 2346 2347 namespace detail { 2348 2349 template <typename T, typename...> 2350 using enabled_type = T; 2351 2352 namespace hash { 2353 2354 template <typename H, typename K> 2355 constexpr bool meets_requirements() { 2356 return std::is_copy_constructible<H>::value && 2357 std::is_move_constructible<H>::value && 2358 lib::is_invocable_r<std::size_t, H, const K &>::value; 2359 } 2360 2361 template <typename K> 2362 constexpr bool is_enabled() { 2363 using H = std::hash<K>; 2364 return meets_requirements<H, K>() && 2365 std::is_default_constructible<H>::value && 2366 std::is_copy_assignable<H>::value && 2367 std::is_move_assignable<H>::value; 2368 } 2369 2370 } // namespace hash 2371 2372 } // namespace detail 2373 2374 #undef AUTO 2375 #undef AUTO_RETURN 2376 2377 #undef AUTO_REFREF 2378 #undef AUTO_REFREF_RETURN 2379 2380 #undef DECLTYPE_AUTO 2381 #undef DECLTYPE_AUTO_RETURN 2382 2383 } // namespace mpark 2384 2385 namespace std { 2386 2387 template <typename... Ts> 2388 struct hash<mpark::detail::enabled_type< 2389 mpark::variant<Ts...>, 2390 mpark::lib::enable_if_t<mpark::lib::all<mpark::detail::hash::is_enabled< 2391 mpark::lib::remove_const_t<Ts>>()...>::value>>> { 2392 using argument_type = mpark::variant<Ts...>; 2393 using result_type = std::size_t; 2394 2395 inline result_type operator()(const argument_type &v) const { 2396 using mpark::detail::visitation::variant; 2397 std::size_t result = 2398 v.valueless_by_exception() 2399 ? 299792458 // Random value chosen by the universe upon creation 2400 : variant::visit_alt( 2401 #ifdef MPARK_GENERIC_LAMBDAS 2402 [](const auto &alt) { 2403 using alt_type = mpark::lib::decay_t<decltype(alt)>; 2404 using value_type = mpark::lib::remove_const_t< 2405 typename alt_type::value_type>; 2406 return hash<value_type>{}(alt.value); 2407 } 2408 #else 2409 hasher{} 2410 #endif 2411 , 2412 v); 2413 return hash_combine(result, hash<std::size_t>{}(v.index())); 2414 } 2415 2416 private: 2417 #ifndef MPARK_GENERIC_LAMBDAS 2418 struct hasher { 2419 template <typename Alt> 2420 inline std::size_t operator()(const Alt &alt) const { 2421 using alt_type = mpark::lib::decay_t<Alt>; 2422 using value_type = 2423 mpark::lib::remove_const_t<typename alt_type::value_type>; 2424 return hash<value_type>{}(alt.value); 2425 } 2426 }; 2427 #endif 2428 2429 static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { 2430 return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); 2431 } 2432 }; 2433 2434 template <> 2435 struct hash<mpark::monostate> { 2436 using argument_type = mpark::monostate; 2437 using result_type = std::size_t; 2438 2439 inline result_type operator()(const argument_type &) const noexcept { 2440 return 66740831; // return a fundamentally attractive random value. 2441 } 2442 }; 2443 2444 } // namespace std 2445 2446 #endif // MPARK_VARIANT_HPP