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