[PATCH v2 5/5] libstdc++: Make mdspan nothrow movable.
Tomasz Kaminski
tkaminsk@redhat.com
Tue Jul 1 10:35:49 GMT 2025
Hi,
I do not think that the change is necessary, as for the functions default
on the first declaration
(as in the case for the constructors/assigments for mdpsan) have noexcept
specifier deduced
from it body. In other words, I think the test should pass, without adding
the complicated noexcept
conditions.
Regards,
Tomasz
On Fri, Jun 27, 2025 at 11:19 AM Luc Grosheintz <luc.grosheintz@gmail.com>
wrote:
> 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250701/a752d4ed/attachment-0001.htm>
More information about the Libstdc++
mailing list