[PATCH v2 1/4] libstdc++: Merged concept for ranges with static sized.
Jonathan Wakely
jwakely@redhat.com
Tue May 26 09:14:03 GMT 2026
On Fri, 24 Apr 2026 at 08:41 +0200, 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?
OK
> 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);
>- };
>-
> 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
>
>
More information about the Libstdc++
mailing list