]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Implement default_accessor from mdspan.
authorLuc Grosheintz <luc.grosheintz@gmail.com>
Mon, 30 Jun 2025 07:23:16 +0000 (09:23 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Tue, 1 Jul 2025 10:15:50 +0000 (12:15 +0200)
libstdc++-v3/ChangeLog:

* include/std/mdspan (default_accessor): New class.
* src/c++23/std.cc.in: Register default_accessor.
* testsuite/23_containers/mdspan/accessors/default.cc: New test.
* testsuite/23_containers/mdspan/accessors/default_neg.cc: New test.

Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
libstdc++-v3/include/std/mdspan
libstdc++-v3/src/c++23/std.cc.in
libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc [new file with mode: 0644]

index 6dc2441f80bd7c76d35db673e834a92bc345456b..c72a64094b73ea9173384509db47c853eaf67e3f 100644 (file)
@@ -1004,6 +1004,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       [[no_unique_address]] _S_strides_t _M_strides;
     };
 
+  template<typename _ElementType>
+    struct default_accessor
+    {
+      static_assert(!is_array_v<_ElementType>,
+       "ElementType must not be an array type");
+      static_assert(!is_abstract_v<_ElementType>,
+       "ElementType must not be an abstract class type");
+
+      using offset_policy = default_accessor;
+      using element_type = _ElementType;
+      using reference = element_type&;
+      using data_handle_type = element_type*;
+
+      constexpr
+      default_accessor() noexcept = default;
+
+      template<typename _OElementType>
+       requires is_convertible_v<_OElementType(*)[], element_type(*)[]>
+       constexpr
+       default_accessor(default_accessor<_OElementType>) noexcept
+       { }
+
+      constexpr reference
+      access(data_handle_type __p, size_t __i) const noexcept
+      { return __p[__i]; }
+
+      constexpr data_handle_type
+      offset(data_handle_type __p, size_t __i) const noexcept
+      { return __p + __i; }
+    };
+
 _GLIBCXX_END_NAMESPACE_VERSION
 }
 #endif
index 9336118f5d9458e0ed111c00443d9cdf6fbc2657..e692caaa5f9ebaae16bc7262428e84a20fe44463 100644 (file)
@@ -1850,7 +1850,8 @@ export namespace std
   using std::layout_left;
   using std::layout_right;
   using std::layout_stride;
-  // FIXME layout_left_padded, layout_right_padded, default_accessor and mdspan
+  using std::default_accessor;
+  // FIXME layout_left_padded, layout_right_padded, aligned_accessor and mdspan
 }
 #endif
 
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc
new file mode 100644 (file)
index 0000000..c036f8a
--- /dev/null
@@ -0,0 +1,99 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+template<typename Accessor>
+  constexpr void
+  test_accessor_policy()
+  {
+    static_assert(std::copyable<Accessor>);
+    static_assert(std::is_nothrow_move_constructible_v<Accessor>);
+    static_assert(std::is_nothrow_move_assignable_v<Accessor>);
+    static_assert(std::is_nothrow_swappable_v<Accessor>);
+  }
+
+constexpr bool
+test_access()
+{
+  std::default_accessor<double> accessor;
+  std::array<double, 5> a{10, 11, 12, 13, 14};
+  VERIFY(accessor.access(a.data(), 0) == 10);
+  VERIFY(accessor.access(a.data(), 4) == 14);
+  return true;
+}
+
+constexpr bool
+test_offset()
+{
+  std::default_accessor<double> accessor;
+  std::array<double, 5> a{10, 11, 12, 13, 14};
+  VERIFY(accessor.offset(a.data(), 0) == a.data());
+  VERIFY(accessor.offset(a.data(), 4) == a.data() + 4);
+  return true;
+}
+
+class Base
+{ };
+
+class Derived : public Base
+{ };
+
+constexpr void
+test_ctor()
+{
+  // T -> T
+  static_assert(std::is_nothrow_constructible_v<std::default_accessor<double>,
+                                               std::default_accessor<double>>);
+  static_assert(std::is_convertible_v<std::default_accessor<double>,
+                                     std::default_accessor<double>>);
+
+  // T -> const T
+  static_assert(std::is_convertible_v<std::default_accessor<double>,
+                                     std::default_accessor<const double>>);
+  static_assert(std::is_convertible_v<std::default_accessor<Derived>,
+                                     std::default_accessor<const Derived>>);
+
+  // const T -> T
+  static_assert(!std::is_constructible_v<std::default_accessor<double>,
+                                        std::default_accessor<const double>>);
+  static_assert(!std::is_constructible_v<std::default_accessor<Derived>,
+                                        std::default_accessor<const Derived>>);
+
+  // T <-> volatile T
+  static_assert(std::is_convertible_v<std::default_accessor<int>,
+                                     std::default_accessor<volatile int>>);
+  static_assert(!std::is_constructible_v<std::default_accessor<int>,
+                                        std::default_accessor<volatile int>>);
+
+  // size difference
+  static_assert(!std::is_constructible_v<std::default_accessor<char>,
+                                        std::default_accessor<int>>);
+
+  // signedness
+  static_assert(!std::is_constructible_v<std::default_accessor<int>,
+                                        std::default_accessor<unsigned int>>);
+  static_assert(!std::is_constructible_v<std::default_accessor<unsigned int>,
+                                        std::default_accessor<int>>);
+
+  // Derived <-> Base
+  static_assert(!std::is_constructible_v<std::default_accessor<Base>,
+                                        std::default_accessor<Derived>>);
+  static_assert(!std::is_constructible_v<std::default_accessor<Derived>,
+                                        std::default_accessor<Base>>);
+
+}
+
+int
+main()
+{
+  test_accessor_policy<std::default_accessor<double>>();
+  test_access();
+  static_assert(test_access());
+  test_offset();
+  static_assert(test_offset());
+  test_ctor();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc
new file mode 100644 (file)
index 0000000..f8da2b5
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+std::default_accessor<int[3]> a; // { dg-error "required from here" }
+
+class AbstractBase
+{
+  virtual void
+  foo() const = 0;
+};
+
+class Derived : public AbstractBase
+{
+  void
+  foo() const override
+  { }
+};
+
+std::default_accessor<Derived> b_ok;
+std::default_accessor<AbstractBase> b_err; // { dg-error "required from here"}
+
+// { dg-prune-output "ElementType must not be an array type" }
+// { dg-prune-output "ElementType must not be an abstract" }