[PATCH v2 2/2] libstdc++: Better CTAD for span and mdspan [PR120914].
Tomasz Kaminski
tkaminsk@redhat.com
Tue Jul 8 16:26:07 GMT 2025
On Tue, Jul 8, 2025 at 6:18 PM Luc Grosheintz <luc.grosheintz@gmail.com>
wrote:
>
>
> On 7/8/25 17:11, Tomasz Kaminski wrote:
> > This was merged. Thanks for working on it.
> >
> > However, the constant_wrapper paper accepted in Sofia, modifies the
> concept:
> > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2781r8.html
>
> Interesting! I'll go hiking for 3 days, then I'll look at this and
> write the test related to negative numbers.
>
I will also be off for the rest of the week.
>
> Are you proposing implementing the whole of P2781 or just the mdspan
> related change?
>
Not, only mdspan related change. We can test it on any integral-constant
like that
declares value to be const&. Of course if you are interested in
implementing constant_wrapper,
I would be happy to review it.
>
> >
> > On Tue, Jul 8, 2025 at 1:01 PM Tomasz Kaminski <tkaminsk@redhat.com>
> wrote:
> >
> >> Maybe adding a negative test for the error when converting negative
> values
> >> would be valuable then.
> >> I think we can add it as separate commit later, I will try to get
> >> everything merged today,
> >>
> >> On Tue, Jul 8, 2025 at 12:56 PM Jonathan Wakely <jwakely@redhat.com>
> >> wrote:
> >>
> >>> On Tue, 8 Jul 2025 at 11:46, Tomasz Kaminski <tkaminsk@redhat.com>
> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On Tue, Jul 8, 2025 at 12:08 PM Jonathan Wakely <jwakely@redhat.com>
> >>> wrote:
> >>>>>
> >>>>> On Tue, 8 Jul 2025 at 10:54, Luc Grosheintz <
> luc.grosheintz@gmail.com>
> >>> wrote:
> >>>>>>
> >>>>>> 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.
> >>>>>>
> >>>>>> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
> >>>>>> ---
> >>>>>> libstdc++-v3/include/std/mdspan | 8 ++----
> >>>>>> libstdc++-v3/include/std/span | 20 ++++++++++++++-
> >>>>>> .../23_containers/mdspan/extents/misc.cc | 20 +++++++++++++++
> >>>>>> .../testsuite/23_containers/mdspan/mdspan.cc | 25
> >>> +++++++++++++++++++
> >>>>>> .../testsuite/23_containers/span/deduction.cc | 3 +++
> >>>>>> 5 files changed, 69 insertions(+), 7 deletions(-)
> >>>>>>
> >>>>>> diff --git a/libstdc++-v3/include/std/mdspan
> >>> b/libstdc++-v3/include/std/mdspan
> >>>>>> index 0fd78570b3e..152dcb3e92a 100644
> >>>>>> --- a/libstdc++-v3/include/std/mdspan
> >>>>>> +++ b/libstdc++-v3/include/std/mdspan
> >>>>>> @@ -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>)
> >>>>>> diff --git a/libstdc++-v3/include/std/span
> >>> b/libstdc++-v3/include/std/span
> >>>>>> index 49ab9109d83..5629a71b9bd 100644
> >>>>>> --- a/libstdc++-v3/include/std/span
> >>>>>> +++ b/libstdc++-v3/include/std/span
> >>>>>> @@ -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};
> >>>>>
> >>>>> Are the braces here to detect narrowing conversions?
> >>>>>
> >>>>> (The paper doesn't mention why they're used, as far as I can see)
> >>>>
> >>>> The information is in revision history (a bit hidden):
> >>>> Initialized the maybe-static-ext's specialization with {T::value} to
> >>> prevent conversions from negative values.
> >>>
> >>> Thanks. OK for trunk then.
> >>>
> >>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>> + }
> >>>>>>
> >>>>>> 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 &&)
> >>>>>> diff --git
> >>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> >>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> >>>>>> index e71fdc54230..bca8901685d 100644
> >>>>>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> >>>>>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> >>>>>> @@ -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;
> >>>>>> }
> >>>>>>
> >>>>>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> >>> b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> >>>>>> index 9252273bf66..a650fb19bdf 100644
> >>>>>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> >>>>>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> >>>>>> @@ -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());
> >>>>>>
> >>>>>> diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc
> >>> b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
> >>>>>> index dce6cedf89b..c66db90222e 100644
> >>>>>> --- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc
> >>>>>> +++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
> >>>>>> @@ -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));
> >>>>>> }
> >>>>>> --
> >>>>>> 2.49.0
> >>>>>>
> >>>>>
> >>>
> >>>
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250708/41bad347/attachment-0001.htm>
More information about the Libstdc++
mailing list