diff --git a/Source/Core/Common/Compat/in_place.h b/Source/Core/Common/Compat/in_place.h index 1758216d22..bded66c019 100644 --- a/Source/Core/Common/Compat/in_place.h +++ b/Source/Core/Common/Compat/in_place.h @@ -13,7 +13,7 @@ #include -namespace std +namespace mpark { struct in_place_t { @@ -32,6 +32,7 @@ struct in_place_type_t explicit in_place_type_t() = default; }; +#ifdef MPARK_VARIABLE_TEMPLATES constexpr in_place_t in_place{}; template @@ -39,5 +40,6 @@ constexpr in_place_index_t in_place_index{}; template constexpr in_place_type_t in_place_type{}; +#endif -} // namespace std +} // namespace mpark diff --git a/Source/Core/Common/Compat/variant b/Source/Core/Common/Compat/variant index dc32b6806f..45d8b81d15 100644 --- a/Source/Core/Common/Compat/variant +++ b/Source/Core/Common/Compat/variant @@ -32,18 +32,18 @@ namespace std { template constexpr variant(T&&) noexcept(see below); template - constexpr explicit variant(::std::in_place_type_t, Args&&...); + constexpr explicit variant(in_place_type_t, Args&&...); template constexpr explicit variant( - ::std::in_place_type_t, initializer_list, Args&&...); + in_place_type_t, initializer_list, Args&&...); template - constexpr explicit variant(::std::in_place_index_t, Args&&...); + constexpr explicit variant(in_place_index_t, Args&&...); template constexpr explicit variant( - ::std::in_place_index_t, initializer_list, Args&&...); + in_place_index_t, initializer_list, Args&&...); // 20.7.2.2, destructor ~variant(); @@ -207,7 +207,6 @@ namespace std { #include #include #include -#include "in_place.h" // MPark.Variant // @@ -220,7 +219,7 @@ namespace std { #define MPARK_CONFIG_HPP // MSVC 2015 Update 3. -#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024215) +#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) #error "MPark.Variant requires C++11 support." #endif @@ -228,14 +227,22 @@ namespace std { #define __has_builtin(x) 0 #endif +#ifndef __has_include +#define __has_include(x) 0 +#endif + #ifndef __has_feature #define __has_feature(x) 0 #endif -#if __has_builtin(__builtin_addressof) || __GNUC__ >= 7 || defined(_MSC_VER) +#if __has_builtin(__builtin_addressof) || (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) #define MPARK_BUILTIN_ADDRESSOF #endif +#if __has_builtin(__builtin_unreachable) +#define MPARK_BUILTIN_UNREACHABLE +#endif + #if __has_builtin(__type_pack_element) #define MPARK_TYPE_PACK_ELEMENT #endif @@ -244,7 +251,8 @@ namespace std { #define MPARK_CPP14_CONSTEXPR #endif -#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) +#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ + (defined(_MSC_VER) && defined(_CPPUNWIND)) #define MPARK_EXCEPTIONS #endif @@ -268,8 +276,14 @@ namespace std { #define MPARK_VARIABLE_TEMPLATES #endif +#if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 +#define MPARK_TRIVIALITY_TYPE_TRAITS +#endif + #endif // MPARK_CONFIG_HPP +#include "in_place.h" + // MPark.Variant // // Copyright Michael Park, 2015-2017 @@ -287,6 +301,7 @@ namespace std { #define RETURN(...) \ noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; } + namespace mpark { namespace lib @@ -303,6 +318,7 @@ template struct array { constexpr const T& operator[](std::size_t index) const { return data[index]; } + T data[N == 0 ? 1 : N]; }; @@ -338,22 +354,16 @@ inline constexpr T&& forward(remove_reference_t&& t) noexcept } template -constexpr remove_reference_t&& move(T&& t) noexcept +inline constexpr remove_reference_t&& move(T&& t) noexcept { return static_cast&&>(t); } + #ifdef MPARK_INTEGER_SEQUENCE -template -using integer_sequence = std::integer_sequence; - -template -using index_sequence = std::index_sequence; - -template -using make_index_sequence = std::make_index_sequence; - -template -using index_sequence_for = std::index_sequence_for; +using std::index_sequence; +using std::index_sequence_for; +using std::integer_sequence; +using std::make_index_sequence; #else template struct integer_sequence @@ -475,7 +485,12 @@ template using bool_constant = std::integral_constant; template -using void_t = void; +struct voider : identity +{ +}; + +template +using void_t = typename voider::type; namespace detail { @@ -484,7 +499,7 @@ namespace swappable using std::swap; template -struct is_swappable_impl +struct is_swappable { private: template (), std::declval()))> @@ -494,12 +509,9 @@ private: inline static std::false_type test(...); public: - using type = decltype(test(0)); + static constexpr bool value = decltype(test(0))::value; }; -template -using is_swappable = typename is_swappable_impl::type; - template ::value> struct is_nothrow_swappable { @@ -514,11 +526,8 @@ struct is_nothrow_swappable : std::false_type } // namespace swappable } // namespace detail -template -using is_swappable = detail::swappable::is_swappable; - -template -using is_nothrow_swappable = detail::swappable::is_nothrow_swappable; +using detail::swappable::is_nothrow_swappable; +using detail::swappable::is_swappable; // #ifdef _MSC_VER @@ -669,16 +678,13 @@ using remove_all_extents_t = typename remove_all_extents::type; template using size_constant = std::integral_constant; -template -using bool_sequence = integer_sequence; - template struct indexed_type : size_constant, identity { }; template -using all = std::is_same, bool_sequence>; +using all = std::is_same, integer_sequence>; #ifdef MPARK_TYPE_PACK_ELEMENT template @@ -712,6 +718,52 @@ template using type_pack_element_t = typename type_pack_element::type; #endif +#ifdef MPARK_TRIVIALITY_TYPE_TRAITS +using std::is_trivially_copy_assignable; +using std::is_trivially_copy_constructible; +using std::is_trivially_move_assignable; +using std::is_trivially_move_constructible; +#else +template +struct is_trivially_copy_constructible + : bool_constant::value&& __has_trivial_copy(T)> +{ +}; + +template +struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> +{ +}; + +template +struct is_trivially_copy_assignable + : bool_constant::value&& __has_trivial_assign(T)> +{ +}; + +template +struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> +{ +}; +#endif + +template +struct dependent_type : T +{ +}; + +template +struct push_back; + +template +using push_back_t = typename push_back::type; + +template +struct push_back, J> +{ + using type = index_sequence; +}; + } // namespace lib } // namespace mpark @@ -747,6 +799,7 @@ namespace mpark #define AUTO auto #define AUTO_RETURN(...) \ ->lib::decay_t { return __VA_ARGS__; } + #define AUTO_REFREF auto #define AUTO_REFREF_RETURN(...) \ ->decltype((__VA_ARGS__)) \ @@ -758,6 +811,7 @@ namespace mpark #define DECLTYPE_AUTO auto #define DECLTYPE_AUTO_RETURN(...) \ ->decltype(__VA_ARGS__) { return __VA_ARGS__; } + #endif class bad_variant_access : public std::exception @@ -772,6 +826,9 @@ public: throw bad_variant_access{}; #else std::terminate(); +#ifdef MPARK_BUILTIN_UNREACHABLE + __builtin_unreachable(); +#endif #endif } @@ -828,26 +885,16 @@ struct variant_alternative : std::add_cv -struct variant_alternative> : lib::identity> +struct variant_alternative> { - static_assert(I < sizeof...(Ts), "`variant_alternative` index out of range."); + static_assert(I < sizeof...(Ts), "Index out of bounds in std::variant_alternative<>"); + using type = lib::type_pack_element_t; }; constexpr std::size_t variant_npos = static_cast(-1); namespace detail { -inline constexpr bool all() -{ - return true; -} - -template -inline constexpr bool all(bool b, Bs... bs) -{ - return b && all(bs...); -} - constexpr std::size_t not_found = static_cast(-1); constexpr std::size_t ambiguous = static_cast(-2); @@ -922,9 +969,9 @@ template class IsTriviallyAvailable, template class IsAvailable> inline constexpr Trait trait() { - return IsTriviallyAvailable::value ? Trait::TriviallyAvailable : IsAvailable::value ? - Trait::Available : - Trait::Unavailable; + return IsTriviallyAvailable::value ? + Trait::TriviallyAvailable : + IsAvailable::value ? Trait::Available : Trait::Unavailable; } #ifdef MPARK_CPP14_CONSTEXPR @@ -965,18 +1012,18 @@ template struct traits { static constexpr Trait copy_constructible_trait = common_trait( - trait()...); + trait()...); static constexpr Trait move_constructible_trait = common_trait( - trait()...); + trait()...); static constexpr Trait copy_assignable_trait = - common_trait(copy_constructible_trait, move_constructible_trait, - trait()...); + common_trait(copy_constructible_trait, + trait()...); static constexpr Trait move_assignable_trait = common_trait(move_constructible_trait, - trait()...); + trait()...); static constexpr Trait destructible_trait = common_trait(trait()...); @@ -988,15 +1035,15 @@ struct recursive_union { #ifdef MPARK_RETURN_TYPE_DEDUCTION template - inline static constexpr auto&& get_alt(V&& v, ::std::in_place_index_t<0>) + inline static constexpr auto&& get_alt(V&& v, in_place_index_t<0>) { return lib::forward(v).head_; } template - inline static constexpr auto&& get_alt(V&& v, ::std::in_place_index_t) + inline static constexpr auto&& get_alt(V&& v, in_place_index_t) { - return get_alt(lib::forward(v).tail_, ::std::in_place_index_t{}); + return get_alt(lib::forward(v).tail_, in_place_index_t{}); } #else template @@ -1016,7 +1063,7 @@ struct recursive_union }; template - inline static constexpr AUTO_REFREF get_alt(V&& v, ::std::in_place_index_t) + inline static constexpr AUTO_REFREF get_alt(V&& v, in_place_index_t) AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) #endif }; @@ -1025,8 +1072,7 @@ struct base { template inline static constexpr AUTO_REFREF get_alt(V&& v) - AUTO_REFREF_RETURN(recursive_union::get_alt(lib::forward(v).data_, - ::std::in_place_index_t{})) + AUTO_REFREF_RETURN(recursive_union::get_alt(data(lib::forward(v)), in_place_index_t{})) }; struct variant @@ -1042,7 +1088,6 @@ namespace visitation { struct base { -private: template inline static constexpr const T& at(const T& elem) { @@ -1059,7 +1104,7 @@ private: template inline static constexpr int visit_visitor_return_type_check() { - static_assert(all(std::is_same::value...), + static_assert(lib::all::value...>::value, "`mpark::visit` requires the visitor to have a single " "return type."); return 0; @@ -1103,23 +1148,22 @@ private: -> decltype(make_fdiagonal_impl( lib::make_index_sequence::size()>{})) { - static_assert(all((lib::decay_t::size() == lib::decay_t::size())...), + static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, "all of the variants must be the same size."); return make_fdiagonal_impl(lib::make_index_sequence::size()>{}); } #ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto make_fmatrix_impl(lib::index_sequence is) + template + inline static constexpr auto make_fmatrix_impl(Is is) { return make_dispatch(is); } - template - inline static constexpr auto make_fmatrix_impl(lib::index_sequence, - lib::index_sequence, Ls... ls) + template + inline static constexpr auto make_fmatrix_impl(Is, lib::index_sequence, Ls... ls) { - return make_farray(make_fmatrix_impl(lib::index_sequence{}, ls...)...); + return make_farray(make_fmatrix_impl(lib::push_back_t{}, ls...)...); } template @@ -1135,42 +1179,79 @@ private: template struct impl; - template - struct impl> + template + struct impl { - inline constexpr AUTO operator()() const - AUTO_RETURN(make_dispatch(lib::index_sequence{})) + inline constexpr AUTO operator()() const AUTO_RETURN(make_dispatch(Is{})) }; - template - struct impl, lib::index_sequence, Ls...> + template + struct impl, Ls...> { inline constexpr AUTO operator()() const - AUTO_RETURN(make_farray(impl, Ls...>{}()...)) + AUTO_RETURN(make_farray(impl, Ls...>{}()...)) }; }; template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN( - typename make_fmatrix_impl::template impl< - lib::index_sequence<>, - lib::make_index_sequence::size()>...>{}()) + inline static constexpr AUTO make_fmatrix() + AUTO_RETURN(typename make_fmatrix_impl::template impl< + lib::index_sequence<>, lib::make_index_sequence::size()>...>{}()) #endif +}; // namespace base -public: +template +using FDiagonal = decltype(base::make_fdiagonal()); + +template +struct fdiagonal +{ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4268) +#endif + static constexpr FDiagonal value = base::make_fdiagonal(); +#ifdef _MSC_VER +#pragma warning(pop) +#endif +}; + +template +constexpr FDiagonal fdiagonal::value; + +template +using FMatrix = decltype(base::make_fmatrix()); + +template +struct fmatrix +{ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4268) +#endif + static constexpr FMatrix value = base::make_fmatrix(); +#ifdef _MSC_VER +#pragma warning(pop) +#endif +}; + +template +constexpr FMatrix fmatrix::value; + +struct alt +{ template inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - at(make_fdiagonal(vs)))...>(), - index)(lib::forward(visitor), as_base(lib::forward(vs))...)) + base::at(fdiagonal(vs)))...>::value, + index)(lib::forward(visitor), as_base(lib::forward(vs))...)) template inline static constexpr DECLTYPE_AUTO visit_alt(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - at(make_fmatrix(vs)))...>(), - vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) + base::at(fmatrix(vs)))...>::value, + vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) }; struct variant @@ -1213,13 +1294,13 @@ private: : template inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(base::visit_alt_at(index, lib::forward(visitor), - lib::forward(vs).impl_...)) + DECLTYPE_AUTO_RETURN(alt::visit_alt_at(index, lib::forward(visitor), + lib::forward(vs).impl_...)) template inline static constexpr DECLTYPE_AUTO visit_alt(Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(base::visit_alt(lib::forward(visitor), - lib::forward(vs).impl_...)) + DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), + lib::forward(vs).impl_...)) template inline static constexpr DECLTYPE_AUTO @@ -1247,8 +1328,7 @@ struct alt #pragma warning(disable : 4244) #endif template - inline explicit constexpr alt(::std::in_place_t, Args&&... args) - : value(lib::forward(args)...) + inline explicit constexpr alt(in_place_t, Args&&... args) : value(lib::forward(args)...) { } #ifdef _MSC_VER @@ -1272,15 +1352,16 @@ union recursive_union { \ public: \ inline explicit constexpr recursive_union(valueless_t) noexcept : dummy_{} {} \ + \ template \ - inline explicit constexpr recursive_union(::std::in_place_index_t<0>, Args&&... args) \ - : head_(::std::in_place_t{}, lib::forward(args)...) \ + inline explicit constexpr recursive_union(in_place_index_t<0>, Args&&... args) \ + : head_(in_place_t{}, lib::forward(args)...) \ { \ } \ \ template \ - inline explicit constexpr recursive_union(::std::in_place_index_t, Args&&... args) \ - : tail_(::std::in_place_index_t{}, lib::forward(args)...) \ + inline explicit constexpr recursive_union(in_place_index_t, Args&&... args) \ + : tail_(in_place_index_t{}, lib::forward(args)...) \ { \ } \ \ @@ -1313,14 +1394,14 @@ template class base { public: - inline explicit constexpr base(valueless_t tag) noexcept : data_(tag), - index_(static_cast(-1)) + inline explicit constexpr base(valueless_t tag) noexcept + : data_(tag), index_(static_cast(-1)) { } template - inline explicit constexpr base(::std::in_place_index_t, Args&&... args) - : data_(::std::in_place_index_t{}, lib::forward(args)...), index_(I) + inline explicit constexpr base(in_place_index_t, Args&&... args) + : data_(in_place_index_t{}, lib::forward(args)...), index_(I) { } @@ -1335,12 +1416,21 @@ public: } protected: + using data_t = recursive_union; + friend inline constexpr base& as_base(base& b) { return b; } friend inline constexpr const base& as_base(const base& b) { return b; } friend inline constexpr base&& as_base(base&& b) { return lib::move(b); } friend inline constexpr const base&& as_base(const base&& b) { return lib::move(b); } + + friend inline constexpr data_t& data(base& b) { return b.data_; } + friend inline constexpr const data_t& data(const base& b) { return b.data_; } + friend inline constexpr data_t&& data(base&& b) { return lib::move(b).data_; } + friend inline constexpr const data_t&& data(const base&& b) { return lib::move(b).data_; } + inline static constexpr std::size_t size() { return sizeof...(Ts); } - recursive_union data_; + + data_t data_; index_t index_; friend struct access::base; @@ -1404,7 +1494,7 @@ MPARK_VARIANT_DESTRUCTOR(Trait::Available, ~destructor() { destroy(); }, inline void destroy() noexcept { if (!this->valueless_by_exception()) { - visitation::base::visit_alt(dtor{}, *this); + visitation::alt::visit_alt(dtor{}, *this); } this->index_ = static_cast(-1); }); @@ -1439,7 +1529,7 @@ protected: inline static T& construct_alt(alt& a, Args&&... args) { ::new (static_cast(lib::addressof(a))) - alt(::std::in_place_t{}, lib::forward(args)...); + alt(in_place_t{}, lib::forward(args)...); return a.value; } @@ -1449,17 +1539,17 @@ protected: lhs.destroy(); if (!rhs.valueless_by_exception()) { - visitation::base::visit_alt_at(rhs.index(), + visitation::alt::visit_alt_at(rhs.index(), #ifdef MPARK_GENERIC_LAMBDAS - [](auto& lhs_alt, auto&& rhs_alt) { - constructor::construct_alt( - lhs_alt, lib::forward(rhs_alt).value); - } + [](auto& lhs_alt, auto&& rhs_alt) { + constructor::construct_alt( + lhs_alt, lib::forward(rhs_alt).value); + } #else - ctor {} + ctor {} #endif - , - lhs, lib::forward(rhs)); + , + lhs, lib::forward(rhs)); lhs.index_ = rhs.index_; } } @@ -1488,12 +1578,10 @@ class move_constructor; MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable, move_constructor(move_constructor&& that) = default;); -MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Available, - move_constructor(move_constructor&& that) noexcept( - all(std::is_nothrow_move_constructible::value...)) - : move_constructor(valueless_t{}) { - this->generic_construct(*this, lib::move(that)); - }); +MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Available, move_constructor(move_constructor&& that) noexcept( + lib::all::value...>::value) + : move_constructor(valueless_t{}) { this->generic_construct(*this, lib::move(that)); }); MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor&&) = delete;); @@ -1560,15 +1648,14 @@ protected: template inline void operator()(ThisAlt& this_alt, ThatAlt&& that_alt) const { - self->assign_alt(this_alt, lib::forward(that_alt).value, - std::is_lvalue_reference{}); + self->assign_alt(this_alt, lib::forward(that_alt).value); } assignment* self; }; #endif - template - inline void assign_alt(alt& a, Arg&& arg, lib::bool_constant tag) + template + inline void assign_alt(alt& a, Arg&& arg) { if (this->index() == I) { @@ -1585,12 +1672,13 @@ protected: { struct { - void operator()(std::true_type) const { this_->emplace(T(lib::forward(arg_))); } - void operator()(std::false_type) const { this_->emplace(lib::forward(arg_)); } + void operator()(std::true_type) const { this_->emplace(lib::forward(arg_)); } + void operator()(std::false_type) const { this_->emplace(T(lib::forward(arg_))); } assignment* this_; Arg&& arg_; } impl{this, lib::forward(arg)}; - impl(tag); + impl(lib::bool_constant < std::is_nothrow_constructible::value || + !std::is_nothrow_move_constructible::value > {}); } } @@ -1607,12 +1695,11 @@ protected: } else { - visitation::base::visit_alt_at( + visitation::alt::visit_alt_at( that.index(), #ifdef MPARK_GENERIC_LAMBDAS [this](auto& this_alt, auto&& that_alt) { - this->assign_alt(this_alt, lib::forward(that_alt).value, - std::is_lvalue_reference{}); + this->assign_alt(this_alt, lib::forward(that_alt).value); } #else assigner { this } @@ -1646,13 +1733,13 @@ class move_assignment; MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable, move_assignment& operator=(move_assignment&& that) = default;); -MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::Available, - move_assignment& operator=(move_assignment&& that) noexcept( - all((std::is_nothrow_move_constructible::value && - std::is_nothrow_move_assignable::value)...)) { - this->generic_assign(lib::move(that)); - return *this; - }); +MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Available, move_assignment& operator=(move_assignment&& that) noexcept( + lib::all<(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value)...>::value) { + this->generic_assign(lib::move(that)); + return *this; + }); MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable, move_assignment& operator=(move_assignment&&) = delete;); @@ -1705,7 +1792,7 @@ public: template inline void assign(Arg&& arg) { - this->assign_alt(access::base::get_alt(*this), lib::forward(arg), std::false_type{}); + this->assign_alt(access::base::get_alt(*this), lib::forward(arg)); } inline void swap(impl& that) @@ -1716,17 +1803,17 @@ public: } else if (this->index() == that.index()) { - visitation::base::visit_alt_at(this->index(), + visitation::alt::visit_alt_at(this->index(), #ifdef MPARK_GENERIC_LAMBDAS - [](auto& this_alt, auto& that_alt) { - using std::swap; - swap(this_alt.value, that_alt.value); - } + [](auto& this_alt, auto& that_alt) { + using std::swap; + swap(this_alt.value, that_alt.value); + } #else - swapper {} + swapper {} #endif - , - *this, that); + , + *this, that); } else { @@ -1781,26 +1868,56 @@ private: } }; +template +struct overload_leaf +{ + using F = lib::size_constant (*)(T); + operator F() const { return nullptr; } +}; + template -struct overload; - -template <> -struct overload<> +struct overload_impl { - void operator()() const {} +private: + template + struct impl; + + template + struct impl> : overload_leaf... + { + }; + +public: + using type = impl>; }; +template +using overload = typename overload_impl::type; + template -struct overload : overload +using best_match = lib::invoke_result_t, T&&>; + +template +struct is_in_place_index : std::false_type { - using overload::operator(); - lib::identity operator()(T) const { return {}; } }; -template -using best_match_t = typename lib::invoke_result_t, T&&>::type; +template +struct is_in_place_index> : std::true_type +{ +}; -} // detail +template +struct is_in_place_type : std::false_type +{ +}; + +template +struct is_in_place_type> : std::true_type +{ +}; + +} // namespace detail template class variant @@ -1820,49 +1937,51 @@ public: template , lib::enable_if_t::value, int> = 0> inline constexpr variant() noexcept(std::is_nothrow_default_constructible::value) - : impl_(::std::in_place_index_t<0>{}) + : impl_(in_place_index_t<0>{}) { } variant(const variant&) = default; variant(variant&&) = default; - template , variant>::value, int> = 0, - typename T = detail::best_match_t, - std::size_t I = detail::find_index_sfinae::value, + template , + lib::enable_if_t::value, int> = 0, + lib::enable_if_t::value, int> = 0, + lib::enable_if_t::value, int> = 0, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, lib::enable_if_t::value, int> = 0> inline constexpr variant(Arg&& arg) noexcept(std::is_nothrow_constructible::value) - : impl_(::std::in_place_index_t{}, lib::forward(arg)) + : impl_(in_place_index_t{}, lib::forward(arg)) { } template , lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant(::std::in_place_index_t, Args&&... args) noexcept( + inline explicit constexpr variant(in_place_index_t, Args&&... args) noexcept( std::is_nothrow_constructible::value) - : impl_(::std::in_place_index_t{}, lib::forward(args)...) + : impl_(in_place_index_t{}, lib::forward(args)...) { } - template , - lib::enable_if_t&, Args...>::value, - int> = 0> + template < + std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, + lib::enable_if_t&, Args...>::value, int> = + 0> inline explicit constexpr variant( - ::std::in_place_index_t, std::initializer_list il, + in_place_index_t, std::initializer_list il, Args&&... args) noexcept(std::is_nothrow_constructible&, Args...>::value) - : impl_(::std::in_place_index_t{}, il, lib::forward(args)...) + : impl_(in_place_index_t{}, il, lib::forward(args)...) { } template ::value, lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant(::std::in_place_type_t, Args&&... args) noexcept( + inline explicit constexpr variant(in_place_type_t, Args&&... args) noexcept( std::is_nothrow_constructible::value) - : impl_(::std::in_place_index_t{}, lib::forward(args)...) + : impl_(in_place_index_t{}, lib::forward(args)...) { } @@ -1871,10 +1990,10 @@ public: lib::enable_if_t&, Args...>::value, int> = 0> inline explicit constexpr variant( - ::std::in_place_type_t, std::initializer_list il, + in_place_type_t, std::initializer_list il, Args&&... args) noexcept(std::is_nothrow_constructible&, Args...>::value) - : impl_(::std::in_place_index_t{}, il, lib::forward(args)...) + : impl_(in_place_index_t{}, il, lib::forward(args)...) { } @@ -1885,8 +2004,8 @@ public: template < typename Arg, lib::enable_if_t, variant>::value, int> = 0, - typename T = detail::best_match_t, - std::size_t I = detail::find_index_sfinae::value, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, lib::enable_if_t<(std::is_assignable::value && std::is_constructible::value), int> = 0> inline variant& operator=(Arg&& arg) noexcept((std::is_nothrow_assignable::value && @@ -1903,10 +2022,10 @@ public: return impl_.template emplace(lib::forward(args)...); } - template , - lib::enable_if_t&, Args...>::value, - int> = 0> + template < + std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, + lib::enable_if_t&, Args...>::value, int> = + 0> inline T& emplace(std::initializer_list il, Args&&... args) { return impl_.template emplace(il, lib::forward(args)...); @@ -1935,10 +2054,13 @@ public: } inline constexpr std::size_t index() const noexcept { return impl_.index(); } - template ::value && - lib::is_swappable::value)...>::value, - int> = 0> + + template < + bool Dummy = true, + lib::enable_if_t< + lib::all, Dummy>::value && + lib::dependent_type, Dummy>::value)...>::value, + int> = 0> inline void swap(variant& that) noexcept(lib::all<(std::is_nothrow_move_constructible::value && lib::is_nothrow_swappable::value)...>::value) @@ -1971,6 +2093,7 @@ template struct generic_get_impl { constexpr generic_get_impl(int) {} + constexpr AUTO_REFREF operator()(V&& v) const AUTO_REFREF_RETURN(access::variant::get_alt(lib::forward(v)).value) }; @@ -2190,13 +2313,7 @@ inline constexpr bool operator>=(const variant& lhs, const variant #endif } -template -inline constexpr DECLTYPE_AUTO visit(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - (detail::all(!vs.valueless_by_exception()...) ? (void)0 : throw_bad_variant_access()), - detail::visitation::variant::visit_value(lib::forward(visitor), - lib::forward(vs)...)) - - struct monostate +struct monostate { }; @@ -2230,6 +2347,56 @@ inline constexpr bool operator!=(monostate, monostate) noexcept return false; } +#ifdef MPARK_CPP14_CONSTEXPR +namespace detail +{ +inline constexpr bool all(std::initializer_list bs) +{ + for (bool b : bs) + { + if (!b) + { + return false; + } + } + return true; +} + +} // namespace detail + +template +inline constexpr decltype(auto) visit(Visitor&& visitor, Vs&&... vs) +{ + return (detail::all({!vs.valueless_by_exception()...}) ? (void)0 : throw_bad_variant_access()), + detail::visitation::variant::visit_value(lib::forward(visitor), + lib::forward(vs)...); +} +#else +namespace detail +{ +template +inline constexpr bool all_impl(const lib::array& bs, std::size_t idx) +{ + return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); +} + +template +inline constexpr bool all(const lib::array& bs) +{ + return all_impl(bs, 0); +} + +} // namespace detail + +template +inline constexpr DECLTYPE_AUTO visit(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( + (detail::all(lib::array{{!vs.valueless_by_exception()...}}) ? + (void)0 : + throw_bad_variant_access()), + detail::visitation::variant::visit_value(lib::forward(visitor), + lib::forward(vs)...)) +#endif + template inline auto swap(variant& lhs, variant& rhs) noexcept(noexcept(lhs.swap(rhs))) -> decltype(lhs.swap(rhs)) @@ -2342,15 +2509,15 @@ struct hash namespace std { -using mpark::variant; -using mpark::visit; -using mpark::holds_alternative; +using mpark::bad_variant_access; using mpark::get; using mpark::get_if; +using mpark::holds_alternative; using mpark::monostate; -using mpark::bad_variant_access; -using mpark::variant_size; +using mpark::variant; using mpark::variant_alternative; using mpark::variant_alternative_t; +using mpark::variant_size; +using mpark::visit; } // namespace std #endif