On Tue, May 19, 2026 at 11:44 PM Patrick Palka <[email protected]> wrote:

> On Fri, 24 Apr 2026, Tomasz Kamiński wrote:
>
> > This patch replaces duplicated __detail::__statically_sized (from
> std/meta)
> > and simd::__static_sized_range (from include/bits/simd_details.h)
> concepts
> > with single range::__static_sized_range. The concept uses the
> implementation
> > based on __statically_sized concept, as it avoids triggering
> instantiations
> > of some class template for each possible size value.
> >
> > libstdc++-v3/ChangeLog:
> >
> >       * include/bits/ranges_base.h (ranges::__static_sized_range):
> >       Define.
> >       * include/bits/simd_details.h (simd::__static_sized_range):
> >       Remove.
> >       (simd::__static_range_size): Use ranges::__static_sized_range.
> >       * include/bits/simd_loadstore.h (simd::unchecked_store):
> >       (simd::unchecked_load): Use ranges::__static_sized_range.
> >       * include/bits/simd_vec.h (basic_vec::basic_vec(_Rg&&,
> flags<_Flags>):
> >       Replace __static_sized_range<_Rg, _S_size> with
> >       ranges::__static_sized_range<_Rg> and traing requires size
> >       for size value.
> >       * include/std/meta (__detail::__statically_sized): Remove.
> >       (std::define_static_array): Use ranges::__static_sized_range.
> >       * testsuite/std/simd/traits_impl.cc: Remove test for
> >       simd::__static_sized_range.
> > ---
> > This is new patch in v2 as similar concepts landed before this series.
> > Using Jakub's version, as it does not require template instantiations.
> >
> > Tested on x86_64-linux. OK for trunk?
> >
> >  libstdc++-v3/include/bits/ranges_base.h        |  6 ++++++
> >  libstdc++-v3/include/bits/simd_details.h       |  9 +--------
> >  libstdc++-v3/include/bits/simd_loadstore.h     |  8 ++++----
> >  libstdc++-v3/include/bits/simd_vec.h           | 12 +++++++-----
> >  libstdc++-v3/include/std/meta                  | 12 +-----------
> >  libstdc++-v3/testsuite/std/simd/traits_impl.cc |  4 ----
> >  6 files changed, 19 insertions(+), 32 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/ranges_base.h
> b/libstdc++-v3/include/bits/ranges_base.h
> > index 519927f5613..fea4100eb09 100644
> > --- a/libstdc++-v3/include/bits/ranges_base.h
> > +++ b/libstdc++-v3/include/bits/ranges_base.h
> > @@ -558,6 +558,12 @@ namespace ranges
> >    template<sized_range _Range>
> >      using range_size_t =
> decltype(ranges::size(std::declval<_Range&>()));
> >
> > +#if __cplusplus > 202302L
> > +  template<typename _Tp>
> > +    concept __static_sized_range = sized_range<_Tp> && requires (_Tp&
> __t)
> > +      { static_cast<char(*)[size_t(ranges::size(__t) >= 0)]>(nullptr);
> };
> > +#endif // C++26
> > +
> >    template<typename _Derived>
> >      requires is_class_v<_Derived> && same_as<_Derived,
> remove_cv_t<_Derived>>
> >      class view_interface; // defined in <bits/ranges_util.h>
> > diff --git a/libstdc++-v3/include/bits/simd_details.h
> b/libstdc++-v3/include/bits/simd_details.h
> > index a1acc5bd946..e2002b6de82 100644
> > --- a/libstdc++-v3/include/bits/simd_details.h
> > +++ b/libstdc++-v3/include/bits/simd_details.h
> > @@ -986,18 +986,11 @@ namespace simd
> >      using mask = basic_mask<sizeof(_Tp), __deduce_abi_t<_Tp, _Np>>;
> >
> >    // [simd.ctor] load constructor constraints
> > -  template <typename _Tp, size_t _Np = -1uz>
> > -    concept __static_sized_range
> > -      = ranges::sized_range<_Tp> && requires(_Tp&& __r) {
> > -     typename integral_constant<size_t, ranges::size(__r)>;
> > -     requires (_Np == -1uz || ranges::size(__r) == _Np);
> > -      };
> > -
>
> I have a slight preference of keeping this concept and just defining it
> in terms of ranges::__static_sized_range so that we don't have to adjust
> any existing uses of __static_sized_range inside <simd>.
>
I was very happy with myself after this change, and finding a way to use
ranges::size(r) directly in signatures. I strongly prefer keeping it.
However, this is based on my understanding that concept checks are cached.
So, because the parameter is orthogonal, we possibly have up to 65
(simd max size is 64 + special -1), to be stored somewhere. Is this correct?
With trailing requires clause, we avoid all of that. And I believe that if
we
could use rangs::size direclty, we should simply do


>
> LGTM either way
>
> >    template <typename _Rg>
> >      consteval size_t
> >      __static_range_size(_Rg& __r)
> >      {
> > -      if constexpr (requires { typename integral_constant<size_t,
> ranges::size(__r)>; })
> > +      if constexpr (ranges::__static_sized_range<_Rg>)
> >       return ranges::size(__r);
> >        else
> >       return dynamic_extent;
> > diff --git a/libstdc++-v3/include/bits/simd_loadstore.h
> b/libstdc++-v3/include/bits/simd_loadstore.h
> > index 20c5fb5cf7f..2390ea289f5 100644
> > --- a/libstdc++-v3/include/bits/simd_loadstore.h
> > +++ b/libstdc++-v3/include/bits/simd_loadstore.h
> > @@ -75,7 +75,7 @@ namespace simd
> >        constexpr bool __allow_out_of_bounds =
> __f._S_test(__allow_partial_loadstore);
> >        constexpr size_t __static_size = __static_range_size(__r);
> >
> > -      if constexpr (!__allow_out_of_bounds && __static_sized_range<_Rg>)
> > +      if constexpr (!__allow_out_of_bounds &&
> ranges::__static_sized_range<_Rg>)
> >       static_assert(ranges::size(__r) >= _RV::size(), "given range must
> have sufficient size");
> >
> >        const auto* __ptr = __f.template
> _S_adjust_pointer<_RV>(ranges::data(__r));
> > @@ -121,7 +121,7 @@ namespace simd
> >        constexpr bool __allow_out_of_bounds =
> __f._S_test(__allow_partial_loadstore);
> >        constexpr auto __static_size = __static_range_size(__r);
> >
> > -      if constexpr (!__allow_out_of_bounds && __static_sized_range<_Rg>)
> > +      if constexpr (!__allow_out_of_bounds &&
> ranges::__static_sized_range<_Rg>)
> >       static_assert(ranges::size(__r) >= _RV::size(), "given range must
> have sufficient size");
> >
> >        const auto* __ptr = __f.template
> _S_adjust_pointer<_RV>(ranges::data(__r));
> > @@ -248,7 +248,7 @@ namespace simd
> >                   "'flag_convert' must be used for conversions that are
> not value-preserving");
> >
> >        constexpr bool __allow_out_of_bounds =
> __f._S_test(__allow_partial_loadstore);
> > -      if constexpr (!__allow_out_of_bounds && __static_sized_range<_Rg>)
> > +      if constexpr (!__allow_out_of_bounds &&
> ranges::__static_sized_range<_Rg>)
> >       static_assert(ranges::size(__r) >= _TV::size(), "given range must
> have sufficient size");
> >
> >        auto* __ptr = __f.template
> _S_adjust_pointer<_TV>(ranges::data(__r));
> > @@ -285,7 +285,7 @@ namespace simd
> >                   "'flag_convert' must be used for conversions that are
> not value-preserving");
> >
> >        constexpr bool __allow_out_of_bounds =
> __f._S_test(__allow_partial_loadstore);
> > -      if constexpr (!__allow_out_of_bounds && __static_sized_range<_Rg>)
> > +      if constexpr (!__allow_out_of_bounds &&
> ranges::__static_sized_range<_Rg>)
> >       static_assert(ranges::size(__r) >= _TV::size(), "given range must
> have sufficient size");
> >
> >        auto* __ptr = __f.template
> _S_adjust_pointer<_TV>(ranges::data(__r));
> > diff --git a/libstdc++-v3/include/bits/simd_vec.h
> b/libstdc++-v3/include/bits/simd_vec.h
> > index 5f3bd7fd2f6..6657587e4d4 100644
> > --- a/libstdc++-v3/include/bits/simd_vec.h
> > +++ b/libstdc++-v3/include/bits/simd_vec.h
> > @@ -1207,14 +1207,15 @@ namespace simd
> >       }
> >
> >        template <ranges::contiguous_range _Rg, typename... _Flags>
> > -     requires __static_sized_range<_Rg, _S_size>
> > +     requires ranges::__static_sized_range<_Rg>
> >         && __vectorizable<ranges::range_value_t<_Rg>>
> >         && __explicitly_convertible_to<ranges::range_value_t<_Rg>,
> value_type>
> >       [[__gnu__::__always_inline__]]
> >       constexpr
> >       basic_vec(_Rg&& __range, flags<_Flags...> __flags = {})
> > -       : basic_vec(_LoadCtorTag(), __flags.template
> _S_adjust_pointer<basic_vec>(
> > -                                     ranges::data(__range)))
> > +     requires (ranges::size(__range) == _S_size)
> > +     : basic_vec(_LoadCtorTag(), __flags.template
> _S_adjust_pointer<basic_vec>(
> > +                                   ranges::data(__range)))
> >       {
> >
>  static_assert(__loadstore_convertible_to<ranges::range_value_t<_Rg>,
> value_type,
> >                                                  _Flags...>);
> > @@ -2072,11 +2073,12 @@ namespace simd
> >       {}
> >
> >        template <ranges::contiguous_range _Rg, typename... _Flags>
> > -     requires __static_sized_range<_Rg, _S_size>
> > +     requires ranges::__static_sized_range<_Rg>
> >         && __vectorizable<ranges::range_value_t<_Rg>>
> >         && __explicitly_convertible_to<ranges::range_value_t<_Rg>,
> value_type>
> >       constexpr
> >       basic_vec(_Rg&& __range, flags<_Flags...> __flags = {})
> > +     requires (ranges::size(__range) == _S_size)
> >       : basic_vec(_LoadCtorTag(),
> >                   __flags.template
> _S_adjust_pointer<basic_vec>(ranges::data(__range)))
> >       {
> > @@ -2245,7 +2247,7 @@ namespace simd
> >
> >    // [simd.overview] deduction guide
> ------------------------------------------
> >    template <ranges::contiguous_range _Rg, typename... _Ts>
> > -    requires __static_sized_range<_Rg>
> > +    requires ranges::__static_sized_range<_Rg>
> >      basic_vec(_Rg&& __r, _Ts...)
> >      -> basic_vec<ranges::range_value_t<_Rg>,
> >                __deduce_abi_t<ranges::range_value_t<_Rg>,
> > diff --git a/libstdc++-v3/include/std/meta
> b/libstdc++-v3/include/std/meta
> > index 21a4df45bfc..bc04dddcb64 100644
> > --- a/libstdc++-v3/include/std/meta
> > +++ b/libstdc++-v3/include/std/meta
> > @@ -640,16 +640,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >        return meta::extract<const ranges::range_value_t<_Rg>*>(__str);
> >      }
> >
> > -  namespace __detail
> > -  {
> > -    template<typename _Rg>
> > -    concept __statically_sized
> > -      = requires(_Rg&& __r) {
> > -     static_cast<char(*)[static_cast<size_t>(ranges::size(__r))
> > -                         >= 0]>(nullptr);
> > -      };
> > -  } // namespace __detail
> > -
> >    template<ranges::input_range _Rg>
> >      consteval auto
> >      define_static_array(_Rg&& __r)
> > @@ -657,7 +647,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >        using _Tp = ranges::range_value_t<_Rg>;
> >        auto __array = meta::reflect_constant_array(__r);
> >        auto __type = meta::type_of(__array);
> > -      if constexpr (__detail::__statically_sized<_Rg>)
> > +      if constexpr (ranges::__static_sized_range<_Rg>)
> >       {
> >         constexpr size_t __extent =
> static_cast<size_t>(ranges::size(__r));
> >         if constexpr (__extent)
> > diff --git a/libstdc++-v3/testsuite/std/simd/traits_impl.cc
> b/libstdc++-v3/testsuite/std/simd/traits_impl.cc
> > index 2f705c7df2f..02e2b690a6a 100644
> > --- a/libstdc++-v3/testsuite/std/simd/traits_impl.cc
> > +++ b/libstdc++-v3/testsuite/std/simd/traits_impl.cc
> > @@ -83,10 +83,6 @@ void test()
> >    static_assert(!__streq_to_1("0"));
> >    static_assert(!__streq_to_1("1 "));
> >
> > -  static_assert(__static_sized_range<int[4]>);
> > -  static_assert(__static_sized_range<int[4], 4>);
> > -  static_assert(__static_sized_range<std::array<int, 4>, 4>);
> > -
> >    static_assert( __value_preserving_convertible_to<int, double>);
> >    static_assert(!__value_preserving_convertible_to<int, float>);
> >    static_assert( __value_preserving_convertible_to<float, double>);
> > --
> > 2.53.0
> >
> >
>

Reply via email to