]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Make the default ctor of mdspan conditionally noexcept.
authorLuc Grosheintz <luc.grosheintz@gmail.com>
Mon, 21 Jul 2025 11:07:37 +0000 (13:07 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Mon, 21 Jul 2025 15:48:02 +0000 (17:48 +0200)
Previously, the default ctor of mdspan was never noexcept, even if all
members of mdspan were nothrow default constructible.

This commit makes mdspan conditionally nothrow default constructible.
A similar strengthening happens in libc++.

libstdc++-v3/ChangeLog:

* include/std/mdspan (mdspan::mdspan): Make default ctor
conditionally noexcept.
* testsuite/23_containers/mdspan/mdspan.cc: Add tests.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
libstdc++-v3/include/std/mdspan
libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc

index 89b9f3c8aba7b27079e7bfdb1b659536a23b44f7..055778d29688063ddcfbb86f16d2f06efe00c23d 100644 (file)
@@ -1114,11 +1114,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr
       mdspan()
       requires (rank_dynamic() > 0)
-          && is_default_constructible_v<data_handle_type>
+         && is_default_constructible_v<data_handle_type>
          && is_default_constructible_v<mapping_type>
-         && is_default_constructible_v<accessor_type>
-      : _M_accessor(), _M_mapping(), _M_handle()
-      { }
+         && is_default_constructible_v<accessor_type> = default;
 
       constexpr
       mdspan(const mdspan& __other) = default;
@@ -1307,9 +1305,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       stride(rank_type __r) const { return _M_mapping.stride(__r); }
 
     private:
-      [[no_unique_address]] accessor_type _M_accessor;
-      [[no_unique_address]] mapping_type _M_mapping;
-      [[no_unique_address]] data_handle_type _M_handle;
+      [[no_unique_address]] accessor_type _M_accessor = accessor_type();
+      [[no_unique_address]] mapping_type _M_mapping = mapping_type();
+      [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
     };
 
   template<typename _CArray>
index 942f6d96dca7c4ef75db67f809be0600474419ac..6ffddd11e9519eb2820be98fbc141c632fbca86a 100644 (file)
@@ -4,6 +4,7 @@
 #include <testsuite_hooks.h>
 #include "int_like.h"
 #include "layout_like.h"
+#include <stdexcept>
 
 constexpr auto dyn = std::dynamic_extent;
 
@@ -114,6 +115,27 @@ test_class_properties_all()
   return true;
 }
 
+template<typename T>
+  class ThrowingDefaultAccessor
+  {
+  public:
+    using element_type = T;
+    using reference = element_type&;
+    using data_handle_type = element_type*;
+    using offset_policy = ThrowingDefaultAccessor;
+
+    ThrowingDefaultAccessor() noexcept(false)
+    { }
+
+    reference
+    access(data_handle_type p, size_t i) const
+    { return p[i]; }
+
+    typename offset_policy::data_handle_type
+    offset(data_handle_type p, size_t i) const
+    { return p + i; }
+  };
+
 constexpr bool
 test_default_ctor()
 {
@@ -130,6 +152,18 @@ test_default_ctor()
   return true;
 }
 
+template<template<typename T> typename Accessor, bool Expected>
+  constexpr void
+  test_nothrow_default_ctor()
+  {
+    using Extents = std::extents<int, dyn>;
+    using Layout = std::layout_left;
+    using MDSpan = std::mdspan<double, Extents, Layout, Accessor<double>>;
+
+    static_assert(std::is_default_constructible_v<MDSpan>);
+    static_assert(std::is_nothrow_default_constructible_v<MDSpan> == Expected);
+  }
+
 constexpr bool
 test_from_other()
 {
@@ -683,6 +717,9 @@ main()
   test_default_ctor();
   static_assert(test_default_ctor());
 
+  test_nothrow_default_ctor<std::default_accessor, true>();
+  test_nothrow_default_ctor<ThrowingDefaultAccessor, false>();
+
   test_from_other();
   static_assert(test_from_other());