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