diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 5fb7770d889..08c5395b54d 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -54,10 +54,9 @@ // C++ < 20 || __cpp_concepts < 202002L || __cpp_constexpr < 201811L #if __cpp_lib_variant < 202106L -# include // Use __aligned_membuf instead of union. +# include // Use __aligned_membuf for storage. #endif - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -209,17 +208,18 @@ namespace __variant __as(const std::variant<_Types...>&& __v) noexcept { return std::move(__v); } - // For C++17: - // _Uninitialized is guaranteed to be a trivially destructible type, - // even if T is not. - // For C++20: - // _Uninitialized is trivially destructible iff T is, so _Variant_union - // needs a constrained non-trivial destructor. +#if __cpp_lib_variant < 202106L template> struct _Uninitialized; +#else + template + struct _Uninitialized; +#endif - template - struct _Uninitialized<_Type, true> + // The primary template is used for trivially destructible types in C++17, + // and for all types in C++20. + template + struct _Uninitialized { template constexpr @@ -227,6 +227,7 @@ namespace __variant : _M_storage(std::forward<_Args>(__args)...) { } +#if __cpp_lib_variant < 202106L constexpr const _Type& _M_get() const & noexcept { return _M_storage; } @@ -238,46 +239,18 @@ namespace __variant constexpr _Type&& _M_get() && noexcept { return std::move(_M_storage); } +#endif _Type _M_storage; }; +#if __cpp_lib_variant < 202106L + // This partial specialization is used for non-trivially destructible types + // in C++17, so that _Uninitialized is trivially destructible and can be + // used as a union member in _Variadic_union. template struct _Uninitialized<_Type, false> { -#if __cpp_lib_variant >= 202106L - template - constexpr - _Uninitialized(in_place_index_t<0>, _Args&&... __args) - : _M_storage(std::forward<_Args>(__args)...) - { } - - constexpr ~_Uninitialized() { } - - _Uninitialized(const _Uninitialized&) = default; - _Uninitialized(_Uninitialized&&) = default; - _Uninitialized& operator=(const _Uninitialized&) = default; - _Uninitialized& operator=(_Uninitialized&&) = default; - - constexpr const _Type& _M_get() const & noexcept - { return _M_storage; } - - constexpr _Type& _M_get() & noexcept - { return _M_storage; } - - constexpr const _Type&& _M_get() const && noexcept - { return std::move(_M_storage); } - - constexpr _Type&& _M_get() && noexcept - { return std::move(_M_storage); } - - struct _Empty_byte { }; - - union { - _Empty_byte _M_empty; - _Type _M_storage; - }; -#else template constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args) @@ -299,7 +272,6 @@ namespace __variant { return std::move(*_M_storage._M_ptr()); } __gnu_cxx::__aligned_membuf<_Type> _M_storage; -#endif }; template @@ -316,6 +288,22 @@ namespace __variant return __variant::__get_n<_Np - 3>( std::forward<_Union>(__u)._M_rest._M_rest._M_rest); } +#else + template + constexpr auto&& + __get_n(_Union&& __u) noexcept + { + if constexpr (_Np == 0) + return std::forward<_Union>(__u)._M_first._M_storage; + else if constexpr (_Np == 1) + return std::forward<_Union>(__u)._M_rest._M_first._M_storage; + else if constexpr (_Np == 2) + return std::forward<_Union>(__u)._M_rest._M_rest._M_first._M_storage; + else + return __variant::__get_n<_Np - 3>( + std::forward<_Union>(__u)._M_rest._M_rest._M_rest); + } +#endif // Returns the typed storage for __v. template @@ -428,6 +416,9 @@ namespace __variant ~_Variadic_union() = default; + // If any alternative type is not trivially destructible then we need a + // user-provided destructor that does nothing. The active alternative + // will be destroyed by _Variant_storage::_M_reset() instead of here. constexpr ~_Variadic_union() requires (!__trivially_destructible) { } @@ -486,7 +477,7 @@ namespace __variant constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), - _M_index{_Np} + _M_index{_Np} { } constexpr void @@ -532,7 +523,7 @@ namespace __variant constexpr _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), - _M_index{_Np} + _M_index{_Np} { } constexpr void