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

Reply via email to