diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index bfec288aded1..03cc4f02a1cd 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -935,7 +935,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // noexcept for consistency with other layouts. template requires is_constructible_v - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(!(extents_type::rank() == 0 + && is_convertible_v<_OExtents, extents_type>)) mapping(const layout_stride::mapping<_OExtents>& __other) noexcept : mapping(__other.extents(), __mdspan::__internal_ctor{}) { __glibcxx_assert(*this == __other); } @@ -1102,7 +1103,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template requires is_constructible_v - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(!(extents_type::rank() == 0 + && is_convertible_v<_OExtents, extents_type>)) mapping(const layout_stride::mapping<_OExtents>& __other) noexcept : mapping(__other.extents(), __mdspan::__internal_ctor{}) { __glibcxx_assert(*this == __other); } @@ -1920,18 +1922,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template requires is_constructible_v<_OExtents, extents_type> - constexpr explicit(_OExtents::rank() > 0) + constexpr explicit(!(_OExtents::rank() == 0 + && is_convertible_v<_OExtents, extents_type>)) mapping(const typename layout_stride::mapping<_OExtents>& __other) : _M_storage(__other) { __glibcxx_assert(*this == __other); } - template - requires __mdspan::__is_left_padded_mapping<_LeftpadMapping> + template + requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping> && is_constructible_v - constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent - || _LeftpadMapping::padding_value == dynamic_extent)) - mapping(const _LeftpadMapping& __other) + typename _LeftPaddedMapping::extents_type> + constexpr explicit( + !is_convertible_v + || _S_rank > 1 && (padding_value != dynamic_extent + || _LeftPaddedMapping::padding_value == dynamic_extent)) + mapping(const _LeftPaddedMapping& __other) : _M_storage(layout_left{}, __other) { } @@ -2081,7 +2087,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template requires is_constructible_v<_OExtents, extents_type> - constexpr explicit(_OExtents::rank() > 0) + constexpr explicit(!(_OExtents::rank() == 0 + && is_convertible_v<_OExtents, extents_type>)) mapping(const typename layout_stride::mapping<_OExtents>& __other) : _M_storage(__other) { __glibcxx_assert(*this == __other); } @@ -2090,8 +2097,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping> && is_constructible_v - constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent - || _RightPaddedMapping::padding_value == dynamic_extent)) + constexpr explicit( + !is_convertible_v + || _S_rank > 1 && (padding_value != dynamic_extent + || _RightPaddedMapping::padding_value == dynamic_extent)) mapping(const _RightPaddedMapping& __other) : _M_storage(layout_right{}, __other) { } @@ -2638,7 +2648,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else __glibcxx_assert(__idx <= __ext.extent(0)); - } +} template constexpr void diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc index 80ae5d8d56a6..b6e4138196de 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc @@ -239,12 +239,8 @@ namespace from_same_layout verify_nothrow_convertible>( std::extents{}); - if constexpr (!is_padded_layout) - verify_nothrow_constructible>( - std::extents{}); - else - verify_convertible>( - std::extents{}); + verify_nothrow_constructible>( + std::extents{}); assert_not_constructible< typename Layout::mapping>, @@ -254,12 +250,8 @@ namespace from_same_layout typename Layout::mapping>, typename Layout::mapping>>(); - if constexpr (!is_padded_layout) - verify_nothrow_constructible>( - std::extents{1}); - else - verify_convertible>( - std::extents{1}); + verify_nothrow_constructible>( + std::extents{1}); verify_nothrow_convertible>( std::extents{}); @@ -349,6 +341,67 @@ namespace from_left_or_right } } +// checks: convertibility of rank == 0 mappings. +namespace from_rank0 +{ + template + constexpr void + verify_ctor() + { + using SMapping = typename SLayout::mapping; + using OMapping = typename OLayout::mapping; + + constexpr bool expected = std::is_convertible_v; + if constexpr (expected) + verify_nothrow_convertible(OMapping{}); + else + verify_nothrow_constructible(OMapping{}); + } + + template + constexpr void + test_rank0_convertibility() + { + using E1 = std::extents; + using E2 = std::extents; + + verify_ctor(); + verify_ctor(); + + verify_ctor(); + verify_ctor(); + } + + constexpr void + test_all() + { + auto run = [](Layout) + { + test_rank0_convertibility(); + test_rank0_convertibility(); + test_rank0_convertibility(); + }; + + auto run_all = [run]() + { + run(std::layout_left{}); + run(std::layout_right{}); + run(std::layout_stride{}); +#if __cplusplus > 202302L + run(std::layout_left_padded<0>{}); + run(std::layout_left_padded<1>{}); + run(std::layout_left_padded<6>{}); + run(std::layout_left_padded{}); +#endif + return true; + }; + + run_all(); + static_assert(run_all()); + } +} + // ctor: mapping(layout_stride::mapping) namespace from_stride { @@ -409,8 +462,7 @@ namespace from_stride verify_nothrow_convertible>( std::extents{}); - // Rank == 0 doesn't check IndexType for convertibility. - verify_nothrow_convertible>( + verify_nothrow_constructible>( std::extents{}); verify_nothrow_constructible>( @@ -474,5 +526,7 @@ main() from_left_or_right::test_all(); from_left_or_right::test_all(); + + from_rank0::test_all(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc index 19fdf93ce0df..1b6e063d12de 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc @@ -149,7 +149,6 @@ is_same_mapping(const auto& lhs, const auto& rhs) enum class ConversionRule { Never, - Always, Regular }; @@ -159,8 +158,6 @@ should_convert(auto rule) { if constexpr (rule == ConversionRule::Never) return false; - if constexpr (rule == ConversionRule::Always) - return true; else return std::is_convertible_v; @@ -184,7 +181,7 @@ template // There's a twist when both mappings are left-padded. There's two distinct // ctors: a defaulted copy ctor and a constrained template that enables - // construction from left-padded mappings even if their layout_type is + // construction from left-padded mappings even if their layout_type (padding) is // different. The two ctors have different rules regarding conversion. if constexpr (!std::same_as) @@ -329,7 +326,7 @@ template typename Layout> auto check = [](To, auto m) { - constexpr auto cr = std::cw; + constexpr auto cr = std::cw; check_convertible_variants(m, cr); }; @@ -350,7 +347,7 @@ template typename Layout> auto check = [](To, auto m) { - constexpr auto cr = std::cw; + constexpr auto cr = std::cw; check_convertible_variants(m, cr); }; @@ -373,7 +370,7 @@ template typename Layout> typename Layout<6>::mapping msta{E1{}}; typename Layout::mapping mdyn{E1{}}; - constexpr auto calways = std::cw; + constexpr auto cregular = std::cw; constexpr auto cnever = std::cw; auto check = [](To, auto m, auto cr) @@ -381,7 +378,7 @@ template typename Layout> check(Layout<6>{}, msta, cnever); check(Layout<6>{}, mdyn, cnever); - check(Layout{}, msta, calways); + check(Layout{}, msta, cregular); check(Layout{}, mdyn, cnever); }