[RFC v2 4/4] libstdc++: Support types decomposible in tree elements as range_slice equivalent.
Tomasz Kamiński
tkaminsk@redhat.com
Fri Mar 20 07:54:00 GMT 2026
This was originally proposed P3982R0, and was dropped in R1 as extension
that can be added in C++29.
libstdc++-v3/ChangeLog:
* include/bits/version.def (submdspan): Update to arbitrally
selected 202600 value.
* include/bits/version.h: Regenerate.
* include/std/mdspan (__slice_cast): Handle types decomposing
into two or tree elemenst.
* testsuite/23_containers/mdspan/submdspan/canonical_slices.cc:
Test tuple and user-defined 3 elements structure.
* testsuite/23_containers/mdspan/submdspan/subextents.cc:
Likewise.
---
libstdc++-v3/include/bits/version.def | 6 ++++++
libstdc++-v3/include/bits/version.h | 7 ++++++-
libstdc++-v3/include/std/mdspan | 18 ++++++++++++++++--
.../mdspan/submdspan/canonical_slices.cc | 10 ++++++++++
.../mdspan/submdspan/subextents.cc | 10 ++++++++++
5 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index d1f39207107..09bc3a2d900 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1117,6 +1117,12 @@ ftms = {
ftms = {
name = submdspan;
+ values = {
+ v = 202600; // RFC Decompose tuple into tree elements
+ cxxmin = 26;
+ extra_cond = "__glibcxx_constant_wrapper >= 202506L"
+ "&& __cpp_structured_bindings >= 202411L";
+ };
values = {
v = 202503; // P3982R1 Split strided_slice into extent_slice and range_slice for C++26
cxxmin = 26;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 97fb82e0645..2f50389aed9 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1242,7 +1242,12 @@
#undef __glibcxx_want_padded_layouts
#if !defined(__cpp_lib_submdspan)
-# if (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L)
+# if (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L&& __cpp_structured_bindings >= 202411L)
+# define __glibcxx_submdspan 202600L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan)
+# define __cpp_lib_submdspan 202600L
+# endif
+# elif (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L)
# define __glibcxx_submdspan 202503L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan)
# define __cpp_lib_submdspan 202503L
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index f30c5e83d16..d335b0a9aff 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -3365,15 +3365,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else
{
+#if __glibcxx_submdspan >= 202600L
+ auto [__sbegin, __send, ...__sstrides] = std::move(__slice);
+#else
auto [__sbegin, __send] = std::move(__slice);
+#endif
+
auto __cbegin
= __mdspan::__canonical_index<_IndexType>(std::move(__sbegin));
auto __cend
= __mdspan::__canonical_index<_IndexType>(std::move(__send));
auto __cspan
= __mdspan::__canonical_index<_IndexType>(__cend - __cbegin);
- return __mdspan::__canonical_range_slice<_IndexType>(
- __cbegin, __cspan, cw<_IndexType(1)>);
+#if __glibcxx_submdspan >= 202600L
+ static_assert(sizeof...(__sstrides) <= 1u);
+ if constexpr (sizeof...(__sstrides) > 0u)
+ return __mdspan::__canonical_range_slice<_IndexType>(
+ __cbegin, __cspan,
+ __mdspan::__canonical_index<_IndexType>(std::move(__sstrides))...
+ );
+ else
+#endif
+ return __mdspan::__canonical_range_slice<_IndexType>(
+ __cbegin, __cspan, cw<_IndexType(1)>);
}
}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/canonical_slices.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/canonical_slices.cc
index d747ad40de2..519e762e9fd 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/canonical_slices.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/canonical_slices.cc
@@ -234,10 +234,20 @@ test_triple()
return true;
}
+template<typename Lower, typename Upper, typename Stride>
+struct StridedRange
+{
+ Lower lower;
+ Upper upper;
+ Stride stride;
+};
+
constexpr bool
test_triple_all()
{
test_triple<std::range_slice>();
+ test_triple<std::tuple>();
+ test_triple<StridedRange>();
return true;
}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/subextents.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/subextents.cc
index 35927a0276e..e168f47f3fb 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/subextents.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/subextents.cc
@@ -226,11 +226,21 @@ template<template<typename, typename, typename> class Triple,
return true;
}
+template<typename Lower, typename Upper, typename Stride>
+struct StridedRange
+{
+ Lower lower;
+ Upper upper;
+ Stride stride;
+};
+
template<template<int> typename Cw>
constexpr bool
test_from_triple_all()
{
test_from_triple<std::range_slice, Cw>();
+ test_from_triple<std::tuple, Cw>();
+ test_from_triple<StridedRange, Cw>();
return true;
}
--
2.53.0
More information about the Libstdc++
mailing list