mirror of git://gcc.gnu.org/git/gcc.git
libstdc++: Refactor _Variadic_union so _Unitialized<T, false> is not needed [PR112591].
The changes the _Variadic_union implementation, in a way that the _Unitialized<T, false> partial specialization for non-trivial types is not necessary. This is simply done by separating the specialization for __trivially_destructible being true and false, and for the later defining an empty destructor (similarly as it was done using concepts). We also reduce the number of specialization of _Variadic_union, so specialization (int, int) is reused by (string, int, int) and (int, int). This is done by initialization __trivially_destructible with conjunction of is_trivially_destructible_v for remaining components. This is only necessary for non-trivial (false) specialization, as if both _First and _Rest... are trivially destructible, then _Rest must also be. The above change does not regress the fix r14-7259-g2d55d94e5df389 for template depth, and both before and after the change template depth is 266. I have added dg-options to the 87619.cc to catch future regressions. This also add test for PR112591. PR libstdc++/112591 libstdc++-v3/ChangeLog: * include/std/variant (_Variadic_union): Separate specializations for for union of only trivially destructible types (true as first template argument). Unconditionally define destructor for _Variadic_union<false, _First, _Rest...>. * testsuite/20_util/variant/87619.cc: Add limit for the template depth. * testsuite/20_util/variant/112591.cc: New test. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
This commit is contained in:
parent
28f12e889c
commit
09bece00d0
|
|
@ -393,8 +393,29 @@ namespace __variant
|
|||
_Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete;
|
||||
};
|
||||
|
||||
template<bool __trivially_destructible, typename _First, typename... _Rest>
|
||||
union _Variadic_union<__trivially_destructible, _First, _Rest...>
|
||||
template<typename _First, typename... _Rest>
|
||||
union _Variadic_union<true, _First, _Rest...>
|
||||
{
|
||||
constexpr _Variadic_union() : _M_rest() { }
|
||||
|
||||
template<typename... _Args>
|
||||
constexpr
|
||||
_Variadic_union(in_place_index_t<0>, _Args&&... __args)
|
||||
: _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
|
||||
{ }
|
||||
|
||||
template<size_t _Np, typename... _Args>
|
||||
constexpr
|
||||
_Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
|
||||
: _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
|
||||
{ }
|
||||
|
||||
_Uninitialized<_First> _M_first;
|
||||
_Variadic_union<true, _Rest...> _M_rest;
|
||||
};
|
||||
|
||||
template<typename _First, typename... _Rest>
|
||||
union _Variadic_union<false, _First, _Rest...>
|
||||
{
|
||||
constexpr _Variadic_union() : _M_rest() { }
|
||||
|
||||
|
|
@ -410,24 +431,19 @@ namespace __variant
|
|||
: _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
|
||||
{ }
|
||||
|
||||
#if __cpp_lib_variant >= 202106L
|
||||
_Variadic_union(const _Variadic_union&) = default;
|
||||
_Variadic_union(_Variadic_union&&) = default;
|
||||
_Variadic_union& operator=(const _Variadic_union&) = default;
|
||||
_Variadic_union& operator=(_Variadic_union&&) = default;
|
||||
|
||||
~_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)
|
||||
_GLIBCXX20_CONSTEXPR ~_Variadic_union()
|
||||
{ }
|
||||
#endif
|
||||
|
||||
_Uninitialized<_First> _M_first;
|
||||
_Variadic_union<__trivially_destructible, _Rest...> _M_rest;
|
||||
_Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest;
|
||||
};
|
||||
|
||||
// _Never_valueless_alt is true for variant alternatives that can
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// { dg-do run { target c++17 } }
|
||||
|
||||
#include <variant>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
struct NonEmpty { int x; };
|
||||
struct TrivialEmpty {};
|
||||
struct NonTrivialEmpty { ~NonTrivialEmpty() {} };
|
||||
|
||||
template<typename T>
|
||||
struct Compose : T
|
||||
{
|
||||
std::variant<T, int> v;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool testAlias()
|
||||
{
|
||||
Compose<T> c;
|
||||
return static_cast<T*>(&c) == &std::get<T>(c.v);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
VERIFY( !testAlias<NonEmpty>() );
|
||||
VERIFY( !testAlias<TrivialEmpty>() );
|
||||
#if __cplusplus >= 202002L
|
||||
VERIFY( !testAlias<NonTrivialEmpty>() );
|
||||
#else
|
||||
VERIFY( testAlias<NonTrivialEmpty>() );
|
||||
#endif
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do compile { target c++17 } }
|
||||
// { dg-options "-ftemplate-depth=270" }
|
||||
|
||||
#include <variant>
|
||||
#include <utility>
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
|
||||
template<std::size_t I>
|
||||
struct S {
|
||||
~S() {}
|
||||
};
|
||||
|
||||
template <std::size_t... Is>
|
||||
|
|
|
|||
Loading…
Reference in New Issue