mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
libstdc++: Better CTAD for span and mdspan [PR120914].
This implements P3029R1. In P3029R1, the CTAD for span is refined to
permit deducing the extent of the span from an integral constant, e.g.
span((T*) ptr, integral_constant<size_t, 5>{});
is deduced as span<T, 5>. Similarly, in
auto exts = extents(integral_constant<int, 2>);
auto md = mdspan((T*) ptr, integral_constant<int, 2>);
exts and md have types extents<size_t, 2> and mdspan<double,
extents<size_t, 2>>, respectively.
PR libstdc++/120914
libstdc++-v3/ChangeLog:
* include/std/span (span): Update CTAD to enable
integral constants [P3029R1].
* include/std/mdspan (extents): ditto.
(mdspan): ditto.
* testsuite/23_containers/span/deduction.cc: Test deduction
guide.
* testsuite/23_containers/mdspan/extents/misc.cc: ditto.
* testsuite/23_containers/mdspan/mdspan.cc: ditto.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
This commit is contained in:
committed by
Tomasz Kamiński
parent
bb6075e711
commit
9c600a7e6c
@@ -406,10 +406,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
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>
|
||||
@@ -419,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
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
|
||||
{
|
||||
@@ -1316,7 +1312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
&& (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>)
|
||||
|
||||
@@ -476,6 +476,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
};
|
||||
|
||||
// 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>;
|
||||
@@ -489,7 +506,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
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 &&)
|
||||
|
||||
@@ -97,6 +97,25 @@ test_deduction(Extents... exts)
|
||||
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()
|
||||
{
|
||||
@@ -104,6 +123,7 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -245,6 +245,28 @@ test_from_pointer_and_shape()
|
||||
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()
|
||||
{
|
||||
@@ -616,6 +638,9 @@ main()
|
||||
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());
|
||||
|
||||
|
||||
@@ -80,4 +80,7 @@ test01()
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user