]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Implement strided_slice from <mdspan>. [PR110352]
authorLuc Grosheintz <luc.grosheintz@gmail.com>
Thu, 2 Oct 2025 09:27:14 +0000 (11:27 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Wed, 8 Oct 2025 10:32:17 +0000 (12:32 +0200)
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 <jwakely@redhat.com>
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
libstdc++-v3/include/bits/version.def
libstdc++-v3/include/bits/version.h
libstdc++-v3/include/std/mdspan
libstdc++-v3/src/c++23/std.cc.in
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice_neg.cc [new file with mode: 0644]

index 9fe3ad2feda1accbacc0c67d86707cea9f95d72d..7c91a18c6861a4ee6671845cff97de38aa8f7dc1 100644 (file)
@@ -1075,6 +1075,15 @@ ftms = {
   };
 };
 
+ftms = {
+  name = submdspan;
+  no_stdname = true; // TODO: change once complete
+  values = {
+    v = 1;
+    cxxmin = 26;
+  };
+};
+
 ftms = {
   name = ssize;
   values = {
index d9bf5c8145a0d0481689e0494ea01e2c449d3177..044d756de196f19726726dc7e9b14de0a88426a7 100644 (file)
 #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
index 8d2421819a55946e950f7b3eec3c23104d32463a..7acc232024e902692b751d4133c7be5f54ddb3b4 100644 (file)
@@ -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
     {
index c1b4e4c88b769175ed238a2d15e7e0a6f37d97b9..8da78fe955b71f93d02c3714b55b6ba5636267a2 100644 (file)
@@ -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 (file)
index 0000000..c43a821
--- /dev/null
@@ -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 (file)
index 0000000..0f1d791
--- /dev/null
@@ -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" }