On Mon, May 18, 2026 at 10:14 AM Jonathan Wakely <[email protected]> wrote:
> > > On Mon, 18 May 2026, 09:02 Tomasz Kamiński, <[email protected]> wrote: > >> This is specified as const in the standard, and required to be >> const-callable >> per layout mapping requirement. This made calls to is_exhaustive on mdspan >> with such layout ill-formed. >> >> libstdc++-v3/ChangeLog: >> >> * include/std/mdspan (layout_left_padded::is_exhaustive) >> (layout_righ_padded::is_exhaustive): Mark as const. >> * testsuite/23_containers/mdspan/layouts/mapping.cc: Test >> noexcept and >> const-invocability for is_exhaustive, is_strided, and is_unique. >> * testsuite/23_containers/mdspan/layouts/padded.cc: Test >> is_exhaustive on >> const mapping.. >> * testsuite/23_containers/mdspan/layouts/stride.cc: Likewise. >> * testsuite/23_containers/mdspan/mdspan.cc: Checks >> const-invocability >> for is_exhaustive, is_strided, is_unique. >> --- >> This patch fixes both padded layouts mappings. Expands test to check >> const-invocability for all layouts. >> >> Testing on x86_64-linux. *mdspan* test already passed. >> OK for trunk. I would like to backport that to 16 (mdspan::is_exhaustive >> calls >> are ill-formed), any objections? >> > > OK for trunk and 16 > Backported to 16. > > > >> libstdc++-v3/include/std/mdspan | 4 ++-- >> .../testsuite/23_containers/mdspan/layouts/mapping.cc | 8 ++++++++ >> .../testsuite/23_containers/mdspan/layouts/padded.cc | 9 +++++---- >> .../testsuite/23_containers/mdspan/layouts/stride.cc | 2 +- >> libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc | 6 +++--- >> 5 files changed, 19 insertions(+), 10 deletions(-) >> >> diff --git a/libstdc++-v3/include/std/mdspan >> b/libstdc++-v3/include/std/mdspan >> index 5938bf09a94..adc1c0c6421 100644 >> --- a/libstdc++-v3/include/std/mdspan >> +++ b/libstdc++-v3/include/std/mdspan >> @@ -2621,7 +2621,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { return _PaddedStorage::_M_is_always_exhaustive(); } >> >> constexpr bool >> - is_exhaustive() noexcept >> + is_exhaustive() const noexcept >> { return _M_storage._M_is_exhaustive(); } >> >> static constexpr bool >> @@ -2794,7 +2794,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { return _PaddedStorage::_M_is_always_exhaustive(); } >> >> constexpr bool >> - is_exhaustive() noexcept >> + is_exhaustive() const noexcept >> { return _M_storage._M_is_exhaustive(); } >> >> static constexpr bool >> diff --git >> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc >> index 17cfac54113..28aa69eca77 100644 >> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc >> @@ -44,6 +44,14 @@ template<typename Layout, typename Extents> >> static_assert(M::is_always_strided() && M::is_strided()); >> if constexpr (has_static_is_exhaustive<M>) >> static_assert(M::is_always_exhaustive() && M::is_exhaustive()); >> + >> + static_assert(noexcept(M::is_always_unique())); >> + static_assert(noexcept(M::is_always_strided())); >> + static_assert(noexcept(M::is_always_exhaustive())); >> + static_assert(noexcept(std::declval<const M>().is_unique())); >> + static_assert(noexcept(std::declval<const M>().is_strided())); >> + static_assert(noexcept(std::declval<const M>().is_exhaustive())); >> + >> return true; >> } >> >> diff --git >> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc >> index 1b6e063d12d..30e52c10d1c 100644 >> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc >> @@ -509,7 +509,7 @@ template<template<size_t> typename Layout> >> { >> auto exts = std::extents<int>{}; >> >> - auto check = [](auto m) >> + auto check = [](const auto m) >> { >> static_assert(m.is_always_exhaustive()); >> VERIFY(m.is_exhaustive()); >> @@ -529,9 +529,10 @@ constexpr void >> { >> auto check = [](auto exts) >> { >> - auto m = typename PaddedLayout::mapping(exts); >> + const auto m = typename PaddedLayout::mapping(exts); >> static_assert(m.is_always_exhaustive()); >> - VERIFY(m.is_exhaustive()); >> + VERIFY(m.is_exhaustive()); >> + VERIFY(std::as_const(m).is_exhaustive()); >> }; >> >> check(std::extents(4)); >> @@ -554,7 +555,7 @@ template<template<size_t> typename Layout> >> auto ctrue = std::cw<true>; >> auto cfalse= std::cw<false>; >> >> - auto check = [](auto m, auto static_expected, auto runtime_expected) >> + auto check = [](const auto m, auto static_expected, auto >> runtime_expected) >> { >> static_assert(m.is_always_exhaustive() == static_expected); >> VERIFY(m.is_exhaustive() == runtime_expected); >> diff --git >> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc >> index 8d2fad2936f..94deea33e1c 100644 >> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc >> @@ -278,7 +278,7 @@ template<typename Extents, typename Strides> >> constexpr void >> test_is_exhaustive(Extents extents, Strides strides, bool expected) >> { >> - std::layout_stride::mapping<Extents> m(extents, strides); >> + const std::layout_stride::mapping<Extents> m(extents, strides); >> VERIFY(m.is_exhaustive() == expected); >> >> bool always_exhaustive = extents.rank() == 0 || >> m.required_span_size() == 0; >> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc >> index 62ff7201cce..a2e244df3c5 100644 >> --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc >> @@ -720,9 +720,9 @@ template<typename Layout, bool Expected> >> static_assert(noexcept(MDSpan::is_always_exhaustive()) == Expected); >> static_assert(noexcept(MDSpan::is_always_strided()) == Expected); >> >> - static_assert(noexcept(std::declval<MDSpan>().is_unique()) == >> Expected); >> - static_assert(noexcept(std::declval<MDSpan>().is_exhaustive()) == >> Expected); >> - static_assert(noexcept(std::declval<MDSpan>().is_strided()) == >> Expected); >> + static_assert(noexcept(std::declval<const MDSpan>().is_unique()) == >> Expected); >> + static_assert(noexcept(std::declval<const MDSpan>().is_exhaustive()) >> == Expected); >> + static_assert(noexcept(std::declval<const MDSpan>().is_strided()) == >> Expected); >> } >> >> int >> -- >> 2.54.0 >> >>
