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>.

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