template<typename _IndexType, size_t... _Counts>
auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
-> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
-
- template<typename _Tp>
- consteval size_t
- __dynamic_extent() { return dynamic_extent; }
}
template<typename _IndexType, size_t _Rank>
template<typename... _Integrals>
requires (is_convertible_v<_Integrals, size_t> && ...)
explicit extents(_Integrals...) ->
- extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>;
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
struct layout_left
{
&& (sizeof...(_Integrals) > 0)
explicit mdspan(_ElementType*, _Integrals...)
-> mdspan<_ElementType,
- extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>>;
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
template<typename _ElementType, typename _OIndexType, size_t _Nm>
mdspan(_ElementType*, span<_OIndexType, _Nm>)
};
// deduction guides
+ namespace __detail
+ {
+ template<typename _Tp>
+ concept __integral_constant_like = is_integral_v<decltype(_Tp::value)>
+ && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>>
+ && convertible_to<_Tp, decltype(_Tp::value)>
+ && equality_comparable_with<_Tp, decltype(_Tp::value)>
+ && bool_constant<_Tp() == _Tp::value>::value
+ && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>
+ ::value;
+
+ template<typename _Tp>
+ constexpr size_t __maybe_static_ext = dynamic_extent;
+
+ template<__integral_constant_like _Tp>
+ constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value};
+ }
template<typename _Type, size_t _ArrayExtent>
span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
template<contiguous_iterator _Iter, typename _End>
span(_Iter, _End)
- -> span<remove_reference_t<iter_reference_t<_Iter>>>;
+ -> span<remove_reference_t<iter_reference_t<_Iter>>,
+ __detail::__maybe_static_ext<_End>>;
template<ranges::contiguous_range _Range>
span(_Range &&)
VERIFY(e == expected);
}
+constexpr bool
+test_integral_constant_deduction()
+{
+ auto verify = [](auto actual, auto expected)
+ {
+ static_assert(std::same_as<decltype(actual), decltype(expected)>);
+ VERIFY(actual == expected);
+ };
+
+ constexpr auto c1 = std::integral_constant<size_t, 1>{};
+ constexpr auto c2 = std::integral_constant<int, 2>{};
+
+ verify(std::extents(1), std::extents<size_t, dyn>{1});
+ verify(std::extents(c1), std::extents<size_t, 1>{});
+ verify(std::extents(c2), std::extents<size_t, 2>{});
+ verify(std::extents(c1, 2), std::extents<size_t, 1, dyn>{2});
+ return true;
+}
+
constexpr bool
test_deduction_all()
{
test_deduction<1>(1);
test_deduction<2>(1.0, 2.0f);
test_deduction<3>(int(1), short(2), size_t(3));
+ test_integral_constant_deduction();
return true;
}
return true;
}
+constexpr bool
+test_from_pointer_and_integral_constant()
+{
+ std::array<double, 6> buffer{};
+ double * ptr = buffer.data();
+
+ auto verify = [ptr](auto actual, auto exts)
+ {
+ auto expected = std::mdspan<double, decltype(exts)>(ptr, exts);
+ static_assert(std::same_as<decltype(actual), decltype(expected)>);
+ VERIFY(actual.extents() == expected.extents());
+ };
+
+ auto c3 = std::integral_constant<int, 3>{};
+ auto c6 = std::integral_constant<int, 6>{};
+
+ verify(std::mdspan(ptr, 6), std::extents(6));
+ verify(std::mdspan(ptr, c6), std::extents(c6));
+ verify(std::mdspan(ptr, 2, c3), std::extents(2, c3));
+ return true;
+}
+
constexpr bool
test_from_extents()
{
test_from_pointer_and_shape();
static_assert(test_from_pointer_and_shape());
+ test_from_pointer_and_integral_constant();
+ static_assert(test_from_pointer_and_integral_constant());
+
test_from_extents();
static_assert(test_from_extents());
std::span s12(const_cast<const std::span<int>&>(s5));
static_assert( is_dynamic_span<int>(s12) );
+
+ std::span s13(a.data(), std::integral_constant<size_t, 3>{});
+ static_assert( is_static_span<long, 3>(s13));
}