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