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.groshei...@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