For the title, I have created bugzilla PR120914. for this paper: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120914
On Fri, Jul 4, 2025 at 10:34 AM 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. > > 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/p3029.cc: New test. > * testsuite/23_containers/mdspan/p3029.cc: New test. > > Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> > --- > Thanks for working on this. LGTM. Really small comments on where to place the test, and removing __dynamic_extent helper. > libstdc++-v3/include/std/mdspan | 4 +- > libstdc++-v3/include/std/span | 20 ++++++- > .../testsuite/23_containers/mdspan/p3029.cc | 58 +++++++++++++++++++ > .../testsuite/23_containers/span/p3029.cc | 11 ++++ > 4 files changed, 90 insertions(+), 3 deletions(-) > create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/p3029.cc > create mode 100644 libstdc++-v3/testsuite/23_containers/span/p3029.cc > > diff --git a/libstdc++-v3/include/std/mdspan > b/libstdc++-v3/include/std/mdspan > index f64804e2a42..51abf9624e0 100644 > --- a/libstdc++-v3/include/std/mdspan > +++ b/libstdc++-v3/include/std/mdspan > @@ -419,7 +419,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>()...>; > The __dynamic_extent seem to be no longer used, please consider removing it > + extents<size_t, __detail::__maybe_static_ext<_Integrals>...>; > > struct layout_left > { > @@ -1315,7 +1315,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}; > + } > > 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/p3029.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/p3029.cc > new file mode 100644 > index 00000000000..7c38dc00bf4 > --- /dev/null > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/p3029.cc > I would add this test to the mdspan.cc and corresponding extents tests, where we test deduction. > @@ -0,0 +1,58 @@ > +// { dg-do run { target c++23 } } > + > +#include <mdspan> > + > +#include <testsuite_hooks.h> > + > +constexpr size_t dyn = std::dynamic_extent; > + > +constexpr bool > +test_extents() > +{ > + 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_mdspan() > +{ > + 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; > +} > + > +int > +main() > +{ > + test_extents(); > + static_assert(test_extents()); > + > + test_mdspan(); > + static_assert(test_mdspan()); > +} > diff --git a/libstdc++-v3/testsuite/23_containers/span/p3029.cc > b/libstdc++-v3/testsuite/23_containers/span/p3029.cc > new file mode 100644 > index 00000000000..e894255546f > --- /dev/null > +++ b/libstdc++-v3/testsuite/23_containers/span/p3029.cc > There is a deduction.cc test in the mdspan, and I would add this test case here. > @@ -0,0 +1,11 @@ > +// { dg-do compile { target c++20 } } > + > +#include <span> > + > +constexpr void > +test_ctad() > +{ > + std::array<double, 5> a{}; > + std::span s(a.data(), std::integral_constant<size_t, 5>{}); > + static_assert(std::same_as<decltype(s), std::span<double, 5>>); > +} > -- > 2.49.0 > >