From: Luc Grosheintz Date: Tue, 8 Jul 2025 09:49:21 +0000 (+0200) Subject: libstdc++: Better CTAD for span and mdspan [PR120914]. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9c600a7e6cc588d2ee79d764cbf69ad677b1bac5;p=thirdparty%2Fgcc.git 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{}); is deduced as span. Similarly, in auto exts = extents(integral_constant); auto md = mdspan((T*) ptr, integral_constant); exts and md have types extents and mdspan>, 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 Reviewed-by: Tomasz KamiƄski Signed-off-by: Luc Grosheintz --- diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 5a42aead3eb..5d16de5d907 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -406,10 +406,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template auto __build_dextents_type(integer_sequence) -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>; - - template - consteval size_t - __dynamic_extent() { return dynamic_extent; } } template @@ -419,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template requires (is_convertible_v<_Integrals, size_t> && ...) explicit extents(_Integrals...) -> - extents()...>; + extents...>; struct layout_left { @@ -1316,7 +1312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && (sizeof...(_Integrals) > 0) explicit mdspan(_ElementType*, _Integrals...) -> mdspan<_ElementType, - extents()...>>; + extents...>>; template 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 + concept __integral_constant_like = is_integral_v + && !is_same_v> + && convertible_to<_Tp, decltype(_Tp::value)> + && equality_comparable_with<_Tp, decltype(_Tp::value)> + && bool_constant<_Tp() == _Tp::value>::value + && bool_constant(_Tp()) == _Tp::value> + ::value; + + template + constexpr size_t __maybe_static_ext = dynamic_extent; + + template<__integral_constant_like _Tp> + constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value}; + } template span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; @@ -489,7 +506,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template span(_Iter, _End) - -> span>>; + -> span>, + __detail::__maybe_static_ext<_End>>; template 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); + VERIFY(actual == expected); + }; + + constexpr auto c1 = std::integral_constant{}; + constexpr auto c2 = std::integral_constant{}; + + verify(std::extents(1), std::extents{1}); + verify(std::extents(c1), std::extents{}); + verify(std::extents(c2), std::extents{}); + verify(std::extents(c1, 2), std::extents{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 buffer{}; + double * ptr = buffer.data(); + + auto verify = [ptr](auto actual, auto exts) + { + auto expected = std::mdspan(ptr, exts); + static_assert(std::same_as); + VERIFY(actual.extents() == expected.extents()); + }; + + auto c3 = std::integral_constant{}; + auto c6 = std::integral_constant{}; + + 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&>(s5)); static_assert( is_dynamic_span(s12) ); + + std::span s13(a.data(), std::integral_constant{}); + static_assert( is_static_span(s13)); }