[libc++] Backport P3029R1 Better mdspan's CTAD to C++20/23 (#208132)
Also backport - support for `T::value` of a reference type in `integral-constant-like` from P2781R9 `std::constant_wrapper`, and - LWG4351 _`integral-constant-like`_ needs more `remove_cvref_t`. P3029R1 (and its further fixes) should be treated as a Defect Report against C++20/23 to avoid behavior difference in different modes. Other implementations will do or are already doing the same.
This commit is contained in:
parent
c4cb2c0e76
commit
cb6bccc33f
8 changed files with 49 additions and 48 deletions
|
|
@ -61,7 +61,7 @@
|
|||
"`P1068R11 <https://wg21.link/P1068R11>`__","Vector API for random number generation","2024-03 (Tokyo)","","","`#105423 <https://github.com/llvm/llvm-project/issues/105423>`__",""
|
||||
"`P2944R3 <https://wg21.link/P2944R3>`__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Complete|","22","`#105424 <https://github.com/llvm/llvm-project/issues/105424>`__","The changes to ``tuple``'s equality overload from P2165R4 are not yet implemented."
|
||||
"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","","`#105425 <https://github.com/llvm/llvm-project/issues/105425>`__",""
|
||||
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19","`#105426 <https://github.com/llvm/llvm-project/issues/105426>`__",""
|
||||
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19","`#105426 <https://github.com/llvm/llvm-project/issues/105426>`__","Implemented as a DR against C++20 since LLVM 23."
|
||||
"","","","","","",""
|
||||
"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20","`#105427 <https://github.com/llvm/llvm-project/issues/105427>`__",""
|
||||
"`P2997R1 <https://wg21.link/P2997R1>`__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete|","19","`#105428 <https://github.com/llvm/llvm-project/issues/105428>`__","Implemented as a DR against C++20. (MSVC STL and libstdc++ will do the same.)"
|
||||
|
|
|
|||
|
|
|
@ -466,15 +466,9 @@ using dims = dextents<_IndexType, _Rank>;
|
|||
# endif
|
||||
|
||||
// Deduction guide for extents
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
template <class... _IndexTypes>
|
||||
requires(is_convertible_v<_IndexTypes, size_t> && ...)
|
||||
explicit extents(_IndexTypes...) -> extents<size_t, __maybe_static_ext<_IndexTypes>...>;
|
||||
# else
|
||||
template <class... _IndexTypes>
|
||||
requires(is_convertible_v<_IndexTypes, size_t> && ...)
|
||||
explicit extents(_IndexTypes...) -> extents<size_t, size_t(((void)sizeof(_IndexTypes), dynamic_extent))...>;
|
||||
# endif
|
||||
|
||||
namespace __mdspan_detail {
|
||||
|
||||
|
|
|
|||
|
|
@ -312,17 +312,10 @@ private:
|
|||
# endif
|
||||
};
|
||||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
template <class _ElementType, class... _OtherIndexTypes>
|
||||
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
|
||||
explicit mdspan(_ElementType*, _OtherIndexTypes...)
|
||||
-> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
|
||||
# else
|
||||
template <class _ElementType, class... _OtherIndexTypes>
|
||||
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
|
||||
explicit mdspan(_ElementType*, _OtherIndexTypes...)
|
||||
-> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
|
||||
# endif
|
||||
|
||||
template <class _Pointer>
|
||||
requires(is_pointer_v<remove_reference_t<_Pointer>>)
|
||||
|
|
|
|||
|
|
@ -411,14 +411,10 @@ namespace std {
|
|||
mdspan(Pointer&&)
|
||||
-> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
|
||||
|
||||
template<class ElementType, class... Integrals>
|
||||
requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
|
||||
explicit mdspan(ElementType*, Integrals...)
|
||||
-> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>; // until C++26
|
||||
template<class ElementType, class... Integrals>
|
||||
requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
|
||||
explicit mdspan(ElementType*, Integrals...)
|
||||
-> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>; // since C++26
|
||||
-> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;
|
||||
|
||||
template<class ElementType, class OtherIndexType, size_t N>
|
||||
mdspan(ElementType*, span<OtherIndexType, N>)
|
||||
|
|
|
|||
|
|
@ -19,16 +19,16 @@ namespace std {
|
|||
inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
|
||||
|
||||
template<class T>
|
||||
concept integral-constant-like = // exposition only, since C++26
|
||||
is_integral_v<decltype(T::value)> &&
|
||||
!is_same_v<bool, remove_const_t<decltype(T::value)>> &&
|
||||
concept integral-constant-like = // exposition only
|
||||
is_integral_v<remove_cvref_t<decltype(T::value)>> &&
|
||||
!is_same_v<bool, remove_cvref_t<decltype(T::value)>> &&
|
||||
convertible_to<T, decltype(T::value)> &&
|
||||
equality_comparable_with<T, decltype(T::value)> &&
|
||||
bool_constant<T() == T::value>::value &&
|
||||
bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
|
||||
|
||||
template<class T>
|
||||
constexpr size_t maybe-static-ext = dynamic_extent; // exposition only, since C++26
|
||||
constexpr size_t maybe-static-ext = dynamic_extent; // exposition only
|
||||
template<integral-constant-like T>
|
||||
constexpr size_t maybe-static-ext<T> = {T::value};
|
||||
|
||||
|
|
@ -123,9 +123,7 @@ private:
|
|||
};
|
||||
|
||||
template<class It, class EndOrSize>
|
||||
span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>; // until C++26
|
||||
template<class It, class EndOrSize>
|
||||
span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>; // since C++26
|
||||
span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>;
|
||||
|
||||
template<class T, size_t N>
|
||||
span(T (&)[N]) -> span<T, N>;
|
||||
|
|
@ -597,7 +595,6 @@ template <class _Tp, size_t _Extent>
|
|||
return __s.__as_writable_bytes();
|
||||
}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
template <class _Tp>
|
||||
concept __integral_constant_like =
|
||||
is_integral_v<remove_cvref_t<decltype(_Tp::value)>> && !is_same_v<bool, remove_cvref_t<decltype(_Tp::value)>> &&
|
||||
|
|
@ -613,10 +610,6 @@ inline constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value};
|
|||
|
||||
template <contiguous_iterator _It, class _EndOrSize>
|
||||
span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>, __maybe_static_ext<_EndOrSize>>;
|
||||
# else
|
||||
template <contiguous_iterator _It, class _EndOrSize>
|
||||
span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
|
||||
# endif
|
||||
|
||||
template <class _Tp, size_t _Sz>
|
||||
span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
// explicit extents(Integrals...) -> see below;
|
||||
// Constraints: (is_convertible_v<Integrals, size_t> && ...) is true.
|
||||
//
|
||||
// Remarks: The deduced type is dextents<size_t, sizeof...(Integrals)>. // until C++26
|
||||
// Remarks: The deduced type is extents<size_t, maybe-static-ext<Integrals>...>. // since C++26
|
||||
// Remarks: The deduced type is extents<size_t, maybe-static-ext<Integrals>...>.
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
|
@ -31,6 +30,9 @@ struct NoDefaultCtorIndex {
|
|||
constexpr operator size_t() const noexcept { return value; }
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
using size_ref_constant = std::integral_constant<const std::size_t&, std::integral_constant<std::size_t, N>::value>;
|
||||
|
||||
template <class E, class Expected>
|
||||
constexpr void test(E e, Expected expected) {
|
||||
ASSERT_SAME_TYPE(E, Expected);
|
||||
|
|
@ -47,13 +49,16 @@ constexpr bool test() {
|
|||
std::extents<std::size_t, D, D, D, D, D, D, D, D, D>(1, 2u, 3, 4, 5, 6, 7, 8, 9));
|
||||
test(std::extents(NoDefaultCtorIndex{1}, NoDefaultCtorIndex{2}), std::extents<std::size_t, D, D>(1, 2));
|
||||
|
||||
#if _LIBCPP_STD_VER >= 26
|
||||
// P3029R1: deduction from `integral_constant`
|
||||
test(std::extents(std::integral_constant<size_t, 5>{}), std::extents<std::size_t, 5>());
|
||||
test(std::extents(std::integral_constant<size_t, 5>{}, 6), std::extents<std::size_t, 5, std::dynamic_extent>(6));
|
||||
test(std::extents(std::integral_constant<size_t, 5>{}, 6, std::integral_constant<size_t, 7>{}),
|
||||
std::extents<std::size_t, 5, std::dynamic_extent, 7>(6));
|
||||
#endif
|
||||
// support for `T::value` of a reference type from P2781R9 `std::constant_wrapper`
|
||||
test(std::extents(size_ref_constant<5>{}), std::extents<std::size_t, 5>());
|
||||
test(std::extents(size_ref_constant<5>{}, 6), std::extents<std::size_t, 5, std::dynamic_extent>(6));
|
||||
test(std::extents(std::integral_constant<size_t, 5>{}, 6, size_ref_constant<7>{}),
|
||||
std::extents<std::size_t, 5, std::dynamic_extent, 7>(6));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,7 @@
|
|||
// template<class ElementType, class... Integrals>
|
||||
// requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
|
||||
// explicit mdspan(ElementType*, Integrals...)
|
||||
// -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>; // until C++26
|
||||
// template<class ElementType, class... Integrals>
|
||||
// requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
|
||||
// explicit mdspan(ElementType*, Integrals...)
|
||||
// -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>; // since C++26
|
||||
// -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>;
|
||||
//
|
||||
// template<class ElementType, class OtherIndexType, size_t N>
|
||||
// mdspan(ElementType*, span<OtherIndexType, N>)
|
||||
|
|
@ -53,6 +49,7 @@
|
|||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <concepts>
|
||||
#include <span> // dynamic_extent
|
||||
#include <type_traits>
|
||||
|
|
@ -98,6 +95,9 @@ struct SizeTIntType {
|
|||
constexpr operator size_t() const noexcept { return size_t(val); }
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
using size_ref_constant = std::integral_constant<const std::size_t&, std::integral_constant<std::size_t, N>::value>;
|
||||
|
||||
template <class H, class A>
|
||||
requires(sizeof(decltype(std::mdspan(std::declval<H>(), 10))) > 0)
|
||||
constexpr bool test_no_layout_deduction_guides(const H& handle, const A&) {
|
||||
|
|
@ -107,7 +107,6 @@ constexpr bool test_no_layout_deduction_guides(const H& handle, const A&) {
|
|||
// deduction from pointer and integral like
|
||||
ASSERT_SAME_TYPE(decltype(std::mdspan(handle, 5, SizeTIntType(6))), std::mdspan<T, std::dextents<size_t, 2>>);
|
||||
|
||||
#if _LIBCPP_STD_VER >= 26
|
||||
// P3029R1: deduction from `integral_constant`
|
||||
ASSERT_SAME_TYPE(
|
||||
decltype(std::mdspan(handle, std::integral_constant<size_t, 5>{})), std::mdspan<T, std::extents<size_t, 5>>);
|
||||
|
|
@ -117,7 +116,13 @@ constexpr bool test_no_layout_deduction_guides(const H& handle, const A&) {
|
|||
decltype(std::mdspan(
|
||||
handle, std::integral_constant<size_t, 5>{}, std::dynamic_extent, std::integral_constant<size_t, 7>{})),
|
||||
std::mdspan<T, std::extents<size_t, 5, std::dynamic_extent, 7>>);
|
||||
#endif
|
||||
// support for `T::value` of a reference type from P2781R9 `std::constant_wrapper`
|
||||
ASSERT_SAME_TYPE(decltype(std::mdspan(handle, size_ref_constant<5>{})), std::mdspan<T, std::extents<std::size_t, 5>>);
|
||||
ASSERT_SAME_TYPE(decltype(std::mdspan(handle, size_ref_constant<5>{}, std::dynamic_extent)),
|
||||
std::mdspan<T, std::extents<std::size_t, 5, std::dynamic_extent>>);
|
||||
ASSERT_SAME_TYPE(decltype(std::mdspan(
|
||||
handle, std::integral_constant<std::size_t, 5>{}, std::dynamic_extent, size_ref_constant<7>{})),
|
||||
std::mdspan<T, std::extents<std::size_t, 5, std::dynamic_extent, 7>>);
|
||||
|
||||
std::array<char, 3> exts;
|
||||
// deduction from pointer and array
|
||||
|
|
|
|||
|
|
@ -11,10 +11,7 @@
|
|||
// <span>
|
||||
|
||||
// template<class It, class EndOrSize>
|
||||
// span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>>; // until C++26
|
||||
// template<class It, class EndOrSize>
|
||||
// span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,
|
||||
// maybe-static-ext<EndOrSize>>; // since C++26
|
||||
// span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>;
|
||||
// template<class T, size_t N>
|
||||
// span(T (&)[N]) -> span<T, N>;
|
||||
// template<class T, size_t N>
|
||||
|
|
@ -27,6 +24,7 @@
|
|||
#include <span>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
@ -50,7 +48,6 @@ void test_iterator_sentinel() {
|
|||
assert(s.data() == std::data(arr));
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 26
|
||||
// P3029R1: deduction from `integral_constant`
|
||||
{
|
||||
std::span s{std::begin(arr), std::integral_constant<size_t, 3>{}};
|
||||
|
|
@ -58,15 +55,33 @@ void test_iterator_sentinel() {
|
|||
assert(s.size() == 3);
|
||||
assert(s.data() == std::data(arr));
|
||||
}
|
||||
|
||||
// support for `T::value` of a reference type from P2781R9 `std::constant_wrapper`
|
||||
{
|
||||
using size_3_ref_type = std::integral_constant<const std::size_t&, std::integral_constant<std::size_t, 3>::value>;
|
||||
std::span s{std::begin(arr), size_3_ref_type{}};
|
||||
ASSERT_SAME_TYPE(decltype(s), std::span<int, 3>);
|
||||
assert(s.size() == 3);
|
||||
assert(s.data() == std::data(arr));
|
||||
}
|
||||
#if TEST_STD_VER >= 26
|
||||
{
|
||||
std::span s{std::begin(arr), std::cw<3>};
|
||||
ASSERT_SAME_TYPE(decltype(s), std::span<int, 3>);
|
||||
assert(s.size() == 3);
|
||||
assert(s.data() == std::data(arr));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// LWG4351 integral-constant-like needs more remove_cvref_t
|
||||
using true_ref_type = std::integral_constant<const bool&, std::true_type::value>;
|
||||
LIBCPP_STATIC_ASSERT(!std::__integral_constant_like<true_ref_type>);
|
||||
std::span s(std::begin(arr), true_ref_type{});
|
||||
ASSERT_SAME_TYPE(decltype(s), std::span<int, std::dynamic_extent>);
|
||||
assert(s.size() == 1);
|
||||
assert(s.data() == std::data(arr));
|
||||
}
|
||||
#if TEST_STD_VER >= 26
|
||||
{
|
||||
LIBCPP_STATIC_ASSERT(!std::__integral_constant_like<decltype(std::cw<true>)>);
|
||||
std::span s(std::begin(arr), std::cw<true>);
|
||||
ASSERT_SAME_TYPE(decltype(s), std::span<int, std::dynamic_extent>);
|
||||
|
|
|
|||
Loading…
Reference in a new issue