[PATCH v1] libstdc++: Better CTAD for span and mdspan [P3029].
Tomasz Kaminski
tkaminsk@redhat.com
Mon Jul 7 16:09:23 GMT 2025
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.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.
>
> 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.grosheintz@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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250707/a2789419/attachment.htm>
More information about the Libstdc++
mailing list