On Tue, Sep 2, 2025 at 10:15 AM Luc Grosheintz <[email protected]>
wrote:
> A usecase for P2781R9 is more ergonomic creation of span and mdspan with
> mixed static and dynamic extents, e.g.:
>
> span(ptr, cw<3>)
> extents(cw<3>, 5, cw<7>)
> mdspan(ptr, cw<3>, 5, cw<7>)
>
> should be deduced as:
> span<..., 3>
> extents<..., 3, dyn, 7>
> mdspan<..., extents<..., 3, dyn, 7>>
>
> The change required is to strip cv-qualifiers and references from
> `_Tp::value`, because of:
>
> template<_CwFixedValue _X, typename>
> struct constant_wrapper : _CwOperators
> {
> static constexpr const auto& value = _X._M_data;
>
> libstdc++-v3/ChangeLog:
>
> * include/std/span (__integral_constant_like): Allow the member
> `value` of a constant wrapping type to be a const reference of
> an integer.
> * testsuite/23_containers/mdspan/extents/misc.cc: Add test for
> cw and constant_wrapper.
> * testsuite/23_containers/mdspan/mdspan.cc: Ditto.
> * testsuite/23_containers/span/deduction.cc: Ditto.
>
> Signed-off-by: Luc Grosheintz <[email protected]>
>
Looks very good. Again, I would add test of deducing from bool_constant
and constant_wrapper<bool(x)>, to the tests.
> ---
> libstdc++-v3/include/std/span | 3 ++-
> .../23_containers/mdspan/extents/misc.cc | 20 +++++++++++++------
> .../testsuite/23_containers/mdspan/mdspan.cc | 20 ++++++++++++-------
> .../testsuite/23_containers/span/deduction.cc | 10 ++++++++++
> 4 files changed, 39 insertions(+), 14 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
> index 44f9b36a7ef..f9aa3c77e8e 100644
> --- a/libstdc++-v3/include/std/span
> +++ b/libstdc++-v3/include/std/span
> @@ -480,7 +480,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> namespace __detail
> {
> template<typename _Tp>
> - concept __integral_constant_like =
> is_integral_v<decltype(_Tp::value)>
> + concept __integral_constant_like =
> + is_integral_v<remove_cvref_t<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)>
> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> index 8a43a682004..018c4f95930 100644
> --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
> @@ -98,7 +98,7 @@ test_deduction(Extents... exts)
> }
>
> constexpr bool
> -test_integral_constant_deduction()
> +test_deduction_from_constant()
> {
> auto verify = [](auto actual, auto expected)
> {
> @@ -106,13 +106,21 @@ test_integral_constant_deduction()
> VERIFY(actual == expected);
> };
>
> - constexpr auto c1 = std::integral_constant<size_t, 1>{};
> - constexpr auto c2 = std::integral_constant<int, 2>{};
> + constexpr auto i1 = std::integral_constant<size_t, 1>{};
> + constexpr auto i2 = 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(i1), std::extents<size_t, 1>{});
> + verify(std::extents(i2), std::extents<size_t, 2>{});
> + verify(std::extents(i1, 2), std::extents<size_t, 1, dyn>{2});
> +
> +#if __glibcxx_constant_wrapper
> + constexpr auto c2 = std::constant_wrapper<2>{};
> verify(std::extents(c2), std::extents<size_t, 2>{});
> - verify(std::extents(c1, 2), std::extents<size_t, 1, dyn>{2});
> + verify(std::extents(1, c2), std::extents<size_t, dyn, 2>{1});
> + verify(std::extents(std::cw<2>), std::extents<size_t, 2>{});
> + verify(std::extents(1, std::cw<2>), std::extents<size_t, dyn, 2>{1});
> +#endif
> return true;
> }
>
> @@ -123,7 +131,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();
> + test_deduction_from_constant();
> return true;
> }
>
> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> index bdfc6ebcf56..2583047413c 100644
> --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
> @@ -280,7 +280,7 @@ test_from_pointer_and_shape()
> }
>
> constexpr bool
> -test_from_pointer_and_integral_constant()
> +test_from_pointer_and_constant()
> {
> std::array<double, 6> buffer{};
> double * ptr = buffer.data();
> @@ -292,12 +292,18 @@ test_from_pointer_and_integral_constant()
> VERIFY(actual.extents() == expected.extents());
> };
>
> - auto c3 = std::integral_constant<int, 3>{};
> - auto c6 = std::integral_constant<int, 6>{};
> + auto i3 = std::integral_constant<int, 3>{};
> + auto i6 = 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));
> + verify(std::mdspan(ptr, i6), std::extents(i6));
> + verify(std::mdspan(ptr, 2, i3), std::extents(2, i3));
> +
> +#if __glibcxx_constant_wrapper
> + auto c3 = std::constant_wrapper<3>{};
> + verify(std::mdspan(ptr, 2, c3), std::extents(2, i3));
> + verify(std::mdspan(ptr, 2, std::cw<3>), std::extents(2, i3));
> +#endif
> return true;
> }
>
> @@ -729,8 +735,8 @@ 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_pointer_and_constant();
> + static_assert(test_from_pointer_and_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 c66db90222e..0d045505bed 100644
> --- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc
> +++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
> @@ -83,4 +83,14 @@ test01()
>
> std::span s13(a.data(), std::integral_constant<size_t, 3>{});
> static_assert( is_static_span<long, 3>(s13));
> +
> +#if __glibcxx_constant_wrapper
> + auto c5 = std::constant_wrapper<5>{};
> +
> + std::span s14(a.data(), std::cw<4>);
> + static_assert( is_static_span<long, 4>(s14));
> +
> + std::span s15(a.data(), c5);
> + static_assert( is_static_span<long, 5>(s15));
> +#endif
> }
> --
> 2.51.0
>
>