// noexcept for consistency with other layouts.
template<typename _OExtents>
requires is_constructible_v<extents_type, _OExtents>
- 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); }
template<typename _OExtents>
requires is_constructible_v<extents_type, _OExtents>
- 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); }
template<typename _OExtents>
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<typename _LeftpadMapping>
- requires __mdspan::__is_left_padded_mapping<_LeftpadMapping>
+ template<typename _LeftPaddedMapping>
+ requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping>
&& is_constructible_v<extents_type,
- typename _LeftpadMapping::extents_type>
- 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<typename _LeftPaddedMapping::extents_type,
+ extents_type>
+ || _S_rank > 1 && (padding_value != dynamic_extent
+ || _LeftPaddedMapping::padding_value == dynamic_extent))
+ mapping(const _LeftPaddedMapping& __other)
: _M_storage(layout_left{}, __other)
{ }
template<typename _OExtents>
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); }
requires __mdspan::__is_right_padded_mapping<_RightPaddedMapping>
&& is_constructible_v<extents_type,
typename _RightPaddedMapping::extents_type>
- constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent
- || _RightPaddedMapping::padding_value == dynamic_extent))
+ constexpr explicit(
+ !is_convertible_v<typename _RightPaddedMapping::extents_type,
+ extents_type>
+ || _S_rank > 1 && (padding_value != dynamic_extent
+ || _RightPaddedMapping::padding_value == dynamic_extent))
mapping(const _RightPaddedMapping& __other)
: _M_storage(layout_right{}, __other)
{ }
}
else
__glibcxx_assert(__idx <= __ext.extent(0));
- }
+}
template<typename _IndexType, size_t _Extent, typename _Slice>
constexpr void
verify_nothrow_convertible<Layout, std::extents<unsigned int>>(
std::extents<int>{});
- if constexpr (!is_padded_layout<Layout>)
- verify_nothrow_constructible<Layout, std::extents<int>>(
- std::extents<unsigned int>{});
- else
- verify_convertible<Layout, std::extents<int>>(
- std::extents<unsigned int>{});
+ verify_nothrow_constructible<Layout, std::extents<int>>(
+ std::extents<unsigned int>{});
assert_not_constructible<
typename Layout::mapping<std::extents<int>>,
typename Layout::mapping<std::extents<int, 1>>,
typename Layout::mapping<std::extents<int>>>();
- if constexpr (!is_padded_layout<Layout>)
- verify_nothrow_constructible<Layout, std::extents<int, 1>>(
- std::extents<int, dyn>{1});
- else
- verify_convertible<Layout, std::extents<int, 1>>(
- std::extents<int, dyn>{1});
+ verify_nothrow_constructible<Layout, std::extents<int, 1>>(
+ std::extents<int, dyn>{1});
verify_nothrow_convertible<Layout, std::extents<int, dyn>>(
std::extents<int, 1>{});
}
}
+// checks: convertibility of rank == 0 mappings.
+namespace from_rank0
+{
+ template<typename SLayout, typename OLayout, typename SExtents,
+ typename OExtents>
+ constexpr void
+ verify_ctor()
+ {
+ using SMapping = typename SLayout::mapping<SExtents>;
+ using OMapping = typename OLayout::mapping<OExtents>;
+
+ constexpr bool expected = std::is_convertible_v<OExtents, SExtents>;
+ if constexpr (expected)
+ verify_nothrow_convertible<SMapping>(OMapping{});
+ else
+ verify_nothrow_constructible<SMapping>(OMapping{});
+ }
+
+ template<typename Layout, typename OLayout>
+ constexpr void
+ test_rank0_convertibility()
+ {
+ using E1 = std::extents<int>;
+ using E2 = std::extents<unsigned int>;
+
+ verify_ctor<Layout, OLayout, E1, E2>();
+ verify_ctor<Layout, OLayout, E2, E1>();
+
+ verify_ctor<Layout, OLayout, E2, E2>();
+ verify_ctor<Layout, OLayout, E1, E1>();
+ }
+
+ constexpr void
+ test_all()
+ {
+ auto run = []<typename Layout>(Layout)
+ {
+ test_rank0_convertibility<Layout, std::layout_left>();
+ test_rank0_convertibility<Layout, std::layout_right>();
+ test_rank0_convertibility<Layout, std::layout_stride>();
+ };
+
+ 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<dyn>{});
+#endif
+ return true;
+ };
+
+ run_all();
+ static_assert(run_all());
+ }
+}
+
// ctor: mapping(layout_stride::mapping<OExtents>)
namespace from_stride
{
verify_nothrow_convertible<Layout, std::extents<unsigned int>>(
std::extents<int>{});
- // Rank == 0 doesn't check IndexType for convertibility.
- verify_nothrow_convertible<Layout, std::extents<int>>(
+ verify_nothrow_constructible<Layout, std::extents<int>>(
std::extents<unsigned int>{});
verify_nothrow_constructible<Layout, std::extents<int, 3>>(
from_left_or_right::test_all<std::layout_left, std::layout_right>();
from_left_or_right::test_all<std::layout_right, std::layout_left>();
+
+ from_rank0::test_all();
return 0;
}
enum class ConversionRule
{
Never,
- Always,
Regular
};
{
if constexpr (rule == ConversionRule::Never)
return false;
- if constexpr (rule == ConversionRule::Always)
- return true;
else
return std::is_convertible_v<typename From::extents_type,
typename To::extents_type>;
// 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<LayoutTo, LayoutFrom>)
auto check = []<typename To>(To, auto m)
{
- constexpr auto cr = std::cw<ConversionRule::Always>;
+ constexpr auto cr = std::cw<ConversionRule::Regular>;
check_convertible_variants<To, E1, E2, E3>(m, cr);
};
auto check = []<typename To>(To, auto m)
{
- constexpr auto cr = std::cw<ConversionRule::Always>;
+ constexpr auto cr = std::cw<ConversionRule::Regular>;
check_convertible_variants<To, E1, E2, E3>(m, cr);
};
typename Layout<6>::mapping<E1> msta{E1{}};
typename Layout<dyn>::mapping<E1> mdyn{E1{}};
- constexpr auto calways = std::cw<ConversionRule::Always>;
+ constexpr auto cregular = std::cw<ConversionRule::Regular>;
constexpr auto cnever = std::cw<ConversionRule::Never>;
auto check = []<typename To>(To, auto m, auto cr)
check(Layout<6>{}, msta, cnever);
check(Layout<6>{}, mdyn, cnever);
- check(Layout<dyn>{}, msta, calways);
+ check(Layout<dyn>{}, msta, cregular);
check(Layout<dyn>{}, mdyn, cnever);
}