[PATCH v2] libstdc++: Make is_exhaustive const for layout_(left/right)_padded
Tomasz Kaminski
tkaminsk@redhat.com
Thu May 21 13:34:56 GMT 2026
On Mon, May 18, 2026 at 10:14 AM Jonathan Wakely <jwakely.gcc@gmail.com>
wrote:
>
>
> On Mon, 18 May 2026, 09:02 Tomasz Kamiński, <tkaminsk@redhat.com> 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
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260521/9df5b3fd/attachment.htm>
More information about the Libstdc++
mailing list