On Thu, 4 Sept 2025 at 13:22, Luc Grosheintz <luc.groshei...@gmail.com> 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 <luc.groshei...@gmail.com> > --- > libstdc++-v3/include/std/span | 3 ++- > .../23_containers/mdspan/extents/misc.cc | 22 +++++++++++++----- > .../testsuite/23_containers/mdspan/mdspan.cc | 23 +++++++++++++------ > .../testsuite/23_containers/span/deduction.cc | 20 +++++++++++++++- > 4 files changed, 53 insertions(+), 15 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)>>
We also need remove_cvref_t on this line for the not-bool check, so that constant_wrapper<bool&> doesn't match here, but I haven't opened an LWG issue about that yet, so we can fix that later. This patch is OK for trunk, thanks. > && 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..94086653a74 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,23 @@ 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(std::true_type{}, 2), std::dextents<size_t, 2>{1, 2}); > + verify(std::extents(std::false_type{}, 2), std::dextents<size_t, 2>{0, 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(c2), std::extents<size_t, 2>{}); > + verify(std::extents(1, c2), std::extents<size_t, dyn, 2>{1}); > + verify(std::extents(std::cw<true>, c2), std::extents<size_t, 1, 2>{}); > +#endif > return true; > } > > @@ -123,7 +133,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..ca100b4f314 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,21 @@ 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)); > + verify(std::mdspan(ptr, std::true_type{}, i3), std::extents(1, 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)); > + verify(std::mdspan(ptr, std::cw<true>, std::cw<3>), > + std::extents(std::cw<1>, i3)); > +#endif > return true; > } > > @@ -729,8 +738,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..e958ad5d6db 100644 > --- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc > +++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc > @@ -82,5 +82,23 @@ test01() > 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)); > + static_assert( is_static_span<long, 3>(s13) ); > + > + std::span s14(a.data(), true); > + static_assert( is_dynamic_span<long>(s14) ); > + > + std::span s15(a.data(), std::true_type{}); > + static_assert( is_dynamic_span<long>(s15) ); > + > +#if __glibcxx_constant_wrapper > + auto c5 = std::constant_wrapper<5>{}; > + std::span s16(a.data(), c5); > + static_assert( is_static_span<long, 5>(s16) ); > + > + std::span s17(a.data(), std::cw<4>); > + static_assert( is_static_span<long, 4>(s17) ); > + > + std::span s18(a.data(), std::cw<true>); > + static_assert( is_static_span<long, 1>(s18) ); > +#endif > } > -- > 2.51.0 >