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.

Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com>
---
 libstdc++-v3/include/std/mdspan               | 12 +++---
 .../testsuite/23_containers/mdspan/mdspan.cc  | 37 +++++++++++++++++++
 2 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index f71141f43a9..772ee32db06 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -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;
@@ -1306,9 +1304,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>
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc 
b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
index 942f6d96dca..6ffddd11e95 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
@@ -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());
 
-- 
2.50.0

Reply via email to