https://gcc.gnu.org/g:61061664e89410a023d21b486f37cf687124f8aa
commit r16-4291-g61061664e89410a023d21b486f37cf687124f8aa Author: Luc Grosheintz <[email protected]> Date: Thu Oct 2 11:27:14 2025 +0200 libstdc++: Implement strided_slice from <mdspan>. [PR110352] Adds strided_slice as standardized in N5014. Also creates the internal feature testing macro for submdspan. PR libstdc++/110352 libstdc++-v3/ChangeLog: * include/bits/version.def (submdspan): New internal macro. * include/bits/version.h: Regenerate. * include/std/mdspan (strided_slice): New class. * src/c++23/std.cc.in (strided_slice): Add. * testsuite/23_containers/mdspan/submdspan/strided_slice.cc: New test. * testsuite/23_containers/mdspan/submdspan/strided_slice_neg.cc: New test. Reviewed-by: Jonathan Wakely <[email protected]> Reviewed-by: Tomasz KamiĆski <[email protected]> Signed-off-by: Luc Grosheintz <[email protected]> Diff: --- libstdc++-v3/include/bits/version.def | 9 +++++ libstdc++-v3/include/bits/version.h | 9 +++++ libstdc++-v3/include/std/mdspan | 21 ++++++++++ libstdc++-v3/src/c++23/std.cc.in | 3 +- .../mdspan/submdspan/strided_slice.cc | 46 ++++++++++++++++++++++ .../mdspan/submdspan/strided_slice_neg.cc | 19 +++++++++ 6 files changed, 106 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 9fe3ad2feda1..7c91a18c6861 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1075,6 +1075,15 @@ ftms = { }; }; +ftms = { + name = submdspan; + no_stdname = true; // TODO: change once complete + values = { + v = 1; + cxxmin = 26; + }; +}; + ftms = { name = ssize; values = { diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index d9bf5c8145a0..044d756de196 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1202,6 +1202,15 @@ #endif /* !defined(__cpp_lib_padded_layouts) && defined(__glibcxx_want_padded_layouts) */ #undef __glibcxx_want_padded_layouts +#if !defined(__cpp_lib_submdspan) +# if (__cplusplus > 202302L) +# define __glibcxx_submdspan 1L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan) +# endif +# endif +#endif /* !defined(__cpp_lib_submdspan) && defined(__glibcxx_want_submdspan) */ +#undef __glibcxx_want_submdspan + #if !defined(__cpp_lib_ssize) # if (__cplusplus >= 202002L) # define __glibcxx_ssize 201902L diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 8d2421819a55..7acc232024e9 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -44,6 +44,7 @@ #define __glibcxx_want_mdspan #define __glibcxx_want_aligned_accessor +#define __glibcxx_want_submdspan #include <bits/version.h> #ifdef __glibcxx_mdspan @@ -335,6 +336,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __exts._M_exts._M_dynamic_extents(__begin, __end); } } +#if __glibcxx_submdspan + template<typename _OffsetType, typename _ExtentType, typename _StrideType> + struct strided_slice { + static_assert(__is_standard_integer<_OffsetType>::value + || __detail::__integral_constant_like<_OffsetType>); + static_assert(__is_standard_integer<_ExtentType>::value + || __detail::__integral_constant_like<_ExtentType>); + static_assert(__is_standard_integer<_StrideType>::value + || __detail::__integral_constant_like<_StrideType>); + + using offset_type = _OffsetType; + using extent_type = _ExtentType; + using stride_type = _StrideType; + + [[no_unique_address]] offset_type offset{}; + [[no_unique_address]] extent_type extent{}; + [[no_unique_address]] stride_type stride{}; + }; +#endif + template<typename _IndexType, size_t... _Extents> class extents { diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index c1b4e4c88b76..8da78fe955b7 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -1872,8 +1872,9 @@ export namespace std #if __glibcxx_padded_layouts using std::layout_left_padded; using std::layout_right_padded; + using strided_slice; #endif - // FIXME strided_slice, submdspan_mapping_result, full_extent_t, full_extent, + // FIXME submdspan_mapping_result, full_extent_t, full_extent, // submdspan_extents, mdsubspan } #endif diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc new file mode 100644 index 000000000000..c43a82143214 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc @@ -0,0 +1,46 @@ +// { dg-do run { target c++26 } } +#include <mdspan> + +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr void +check_strided_slice(auto s, auto offset, auto extent, auto stride) +{ + using slice_type = std::strided_slice<decltype(offset), decltype(extent), + decltype(stride)>; + static_assert(std::same_as<decltype(s), slice_type>); + VERIFY(s.offset == offset); + VERIFY(s.extent == extent); + VERIFY(s.stride == stride); +} + +constexpr void +test_initializers(auto offset, auto extent, auto stride) +{ + auto check = [&](auto s) + { + check_strided_slice(s, offset, extent, stride); + }; + + check(std::strided_slice{.offset=offset, .extent=extent, .stride=stride}); + check(std::strided_slice{offset, extent, stride}); + check(std::strided_slice(offset, extent, stride)); +} + +constexpr bool +test_all() +{ + test_initializers(0, 1, 2); + test_initializers(std::integral_constant<short, 0>{}, size_t{1}, std::cw<2>); + test_initializers(-1, 2, 2); + return true; +} + +int +main() +{ + test_all(); + static_assert(test_all()); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice_neg.cc new file mode 100644 index 000000000000..0f1d791d13aa --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice_neg.cc @@ -0,0 +1,19 @@ +// { dg-do compile { target c++26 } } +#include <mdspan> + +#include <cstdint> + +template<typename OffsetType, typename ExtentType, typename StrideType> + constexpr bool + test_invalid() + { + auto s1 = std::strided_slice(OffsetType{}, ExtentType{}, StrideType{}); // { dg-error "required from" } + return true; + } + +static_assert(test_invalid<double, int, int>()); // { dg-error "required from" } +static_assert(test_invalid<int, double, int>()); // { dg-error "required from" } +static_assert(test_invalid<int, int, double>()); // { dg-error "required from" } +static_assert(test_invalid<double, double, double>()); // { dg-error "required from" } + +// { dg-prune-output "static assertion failed" }
