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.
Signed-off-by: Luc Grosheintz <[email protected]>
---
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(-)
create mode 100644
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
create mode 100644
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice_neg.cc
diff --git a/libstdc++-v3/include/bits/version.def
b/libstdc++-v3/include/bits/version.def
index 9fe3ad2feda..7c91a18c686 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 d9bf5c8145a..044d756de19 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 8efd168bcf0..4828806d817 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 c1b4e4c88b7..8da78fe955b 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 00000000000..c43a8214321
--- /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 00000000000..0f1d791d13a
--- /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" }
--
2.50.1