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



>  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
>
>

Reply via email to