On Tue, Jul 8, 2025 at 6:18 PM Luc Grosheintz <luc.groshei...@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 <tkami...@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 <jwak...@redhat.com> > >> wrote: > >> > >>> On Tue, 8 Jul 2025 at 11:46, Tomasz Kaminski <tkami...@redhat.com> > wrote: > >>>> > >>>> > >>>> > >>>> On Tue, Jul 8, 2025 at 12:08 PM Jonathan Wakely <jwak...@redhat.com> > >>> wrote: > >>>>> > >>>>> On Tue, 8 Jul 2025 at 10:54, Luc Grosheintz < > luc.groshei...@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.groshei...@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 > >>>>>> > >>>>> > >>> > >>> > > > >