On Fri, 29 Aug 2025, Patrick Palka wrote:

> On Fri, 29 Aug 2025, Tomasz Kamiński wrote:
> 
> > 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 definining an empty destructor 
> > (similary
> >  as it was done using concepts).
> > 
> > We also reduce the number of specialization of _Varidic_union, so 
> > specialization
> > (int, int) is reused by (string, int, int) and (int,int). This is done by 
> > computing
> > initializating __trivially_destructible with conjuction of 
> > is_trivially_destructible_v
> > for remaining components. This is only necessary for non-trivial (false) 
> > specialization,
> > as if both _First and _Rest... are trivally destructible, then _Rest must 
> > also be.
> > 
> > This also add test for PR112591.
> > ---
> > As in title, this is refernce for comments, espcially if we want to land 
> > this change,
> > or part of it to the trunk regardless of other changes. I think the test is 
> > valuable for sure,
> > but the separate specialization, and removal of _Variadic_union<false, int, 
> > int>
> > specialization seem usefull.
> > 
> > Locally I have removed the _Unitialized<T, false> specialization, and the 
> > objects
> > no longer alias in C++17 mode (112591.cc works the same in C++20/17), and 
> > all
> > test have passed locally, so this seem correct. We could even remove the 
> > _Unitialized
> > altogether and just store _First direclty. This is however ABI break, as it 
> > does 
> > affect layout of classes similar to one in the example.
> > 
> > 
> >  libstdc++-v3/include/std/variant              | 34 ++++++++++++++-----
> >  .../testsuite/20_util/variant/112591.cc       | 32 +++++++++++++++++
> >  2 files changed, 57 insertions(+), 9 deletions(-)
> >  create mode 100644 libstdc++-v3/testsuite/20_util/variant/112591.cc
> > 
> > diff --git a/libstdc++-v3/include/std/variant 
> > b/libstdc++-v3/include/std/variant
> > index 2f44f970028..f2f55837461 100644
> > --- a/libstdc++-v3/include/std/variant
> > +++ b/libstdc++-v3/include/std/variant
> > @@ -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;
> 
> I believe this makes _Variadic_union instantiation quadratic with

(or rather, more quadratic -- instantiating recursive partial
specializations of the form A<T, Ts...> is always quadratic as we need
to build N argument packs of size 1,...,N to pass as Ts.)

> respect to the number of alternatives.  How compile-time/memory
> usage fare for the 87619.cc test with this change?  (can use
> -ftime-report to measure that)
> 
> >      };
> >  
> >    // _Never_valueless_alt is true for variant alternatives that can
> > diff --git a/libstdc++-v3/testsuite/20_util/variant/112591.cc 
> > b/libstdc++-v3/testsuite/20_util/variant/112591.cc
> > new file mode 100644
> > index 00000000000..b1b07c4f46e
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/20_util/variant/112591.cc
> > @@ -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
> > +}
> > -- 
> > 2.50.1
> > 
> > 

Reply via email to