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