[PATCH v2 5/5] libstdc++: Make mdspan nothrow movable.
Luc Grosheintz
luc.grosheintz@gmail.com
Fri Jun 27 09:07:19 GMT 2025
If all members of mdspan are nothrow movable, then mdspan can also
be nothrow movable. The standard doesn't specify that mdspan must be
nothrow movable (when possible). Nothrow movable enables containers
to use move operations even if they have a strong exception guarantee.
This commit strenghtens the exception guarantees for mdspan, making
it nothrow movable if all it's members are nothrow movable.
libstdc++-v3/ChangeLog:
* include/std/mdspan (mdspan): Make nothrow movable, if all
members are nothrow movable.
* testsuite/23_containers/mdspan/mdspan.cc: Test nothrow movable
property.
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
---
libstdc++-v3/include/std/mdspan | 10 +++-
.../testsuite/23_containers/mdspan/mdspan.cc | 53 ++++++++++++++++++-
2 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 852f881971e..563aa312f8a 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -1119,7 +1119,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
mdspan(const mdspan& __other) = default;
constexpr
- mdspan(mdspan&& __other) = default;
+ mdspan(mdspan&& __other)
+ noexcept(is_nothrow_move_constructible_v<accessor_type>
+ && is_nothrow_move_constructible_v<mapping_type>
+ && is_nothrow_move_constructible_v<data_handle_type>) = default;
template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
requires ((sizeof...(_OIndexTypes) == rank()
@@ -1197,7 +1200,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator=(const mdspan& __other) = default;
constexpr mdspan&
- operator=(mdspan&& __other) = default;
+ operator=(mdspan&& __other)
+ noexcept(is_nothrow_move_assignable_v<accessor_type>
+ && is_nothrow_move_assignable_v<mapping_type>
+ && is_nothrow_move_assignable_v<data_handle_type>) = default;
template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
requires (sizeof...(_OIndexTypes) == rank())
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
index d2672878d69..6d8f32ff103 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
@@ -310,11 +310,29 @@ test_from_int_like()
verify(std::mdspan(storage.data(), shape_view));
}
-template<typename T>
+template<typename T, bool NothrowConstructible = true,
+ bool NothrowAssignable = true>
class OpaqueAccessor
{
struct Handle
{
+ constexpr
+ Handle(T * other)
+ : ptr(other)
+ { }
+
+ constexpr
+ Handle(const Handle&) noexcept(NothrowConstructible) = default;
+
+ constexpr
+ Handle(Handle&&) noexcept(NothrowConstructible) = default;
+
+ constexpr Handle&
+ operator=(const Handle&) noexcept(NothrowAssignable) = default;
+
+ constexpr Handle&
+ operator=(Handle&&) noexcept(NothrowAssignable) = default;
+
T * ptr;
};
@@ -489,6 +507,37 @@ test_swap()
return true;
}
+template<bool Constructible, bool Assignable>
+constexpr void
+test_nothrow_movable()
+{
+ using Layout = std::layout_left;
+ using Extents = std::dextents<int, 3>;
+ using Accessor = OpaqueAccessor<int, Constructible, Assignable>;
+ using Handle = Accessor::data_handle_type;
+ static_assert(std::is_nothrow_move_assignable_v<Accessor>);
+ static_assert(std::is_nothrow_move_constructible_v<Accessor>);
+ static_assert(std::is_nothrow_move_assignable_v<Handle> == Assignable);
+ static_assert(std::is_nothrow_move_constructible_v<Handle> == Constructible);
+
+ using MDSpan = std::mdspan<int, Extents, Layout, Accessor>;
+ static_assert(std::is_nothrow_move_assignable_v<MDSpan> == Assignable);
+ static_assert(std::is_nothrow_move_constructible_v<MDSpan> == Constructible);
+}
+
+constexpr void
+test_nothrow_movable_all()
+{
+ using MDSpan = std::mdspan<double, std::dextents<int, 3>>;
+ static_assert(std::is_nothrow_move_assignable_v<MDSpan>);
+ static_assert(std::is_nothrow_move_constructible_v<MDSpan>);
+
+ test_nothrow_movable<true, true>();
+ test_nothrow_movable<true, false>();
+ test_nothrow_movable<false, true>();
+ test_nothrow_movable<false, false>();
+}
+
int
main()
{
@@ -536,5 +585,7 @@ main()
test_swap();
static_assert(test_swap());
+
+ test_nothrow_movable_all();
return 0;
}
--
2.49.0
More information about the Libstdc++
mailing list