On Mon, 23 Feb 2026 at 08:17, Tomasz Kamiński <[email protected]> wrote:
>
> This patch changes the implementation of operator[], to follow similar
> pattern as at, where we normalize argument types and forward to single
> overload. The conversion now uses __mdspan::__index_type_cast, instead
> of static_assert. This introduces asserts assuring that conversion is
> is value preserving.
>
> Finally, __is_multi_index is implemented as local lambda, avoiding
> the need to create a local array with copies of the arguments.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/mdspan (__mdspan::__is_multi_index): Removed,
>         replaced with local lambda in mdspan::operator[].
>         (__mdspan::operator[]): Implement in terms of single overload
>         accepting index_type. Use __mdspan::__index_type_cast for type
>         conversion.
>
> Signed-off-by: Tomasz Kamiński <[email protected]>
> ---
> Tested on x86_64-linux. OK for trunk?

OK

>
>  libstdc++-v3/include/std/mdspan | 43 +++++++++++++--------------------
>  1 file changed, 17 insertions(+), 26 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
> index 3476d42a129..68cdcc9b173 100644
> --- a/libstdc++-v3/include/std/mdspan
> +++ b/libstdc++-v3/include/std/mdspan
> @@ -2906,20 +2906,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      };
>  #endif
>
> -  namespace __mdspan
> -  {
> -    template<typename _Extents, typename _IndexType, size_t _Nm>
> -      constexpr bool
> -      __is_multi_index(const _Extents& __exts, span<_IndexType, _Nm> 
> __indices)
> -      {
> -       static_assert(__exts.rank() == _Nm);
> -       for (size_t __i = 0; __i < __exts.rank(); ++__i)
> -         if (__indices[__i] >= __exts.extent(__i))
> -           return false;
> -       return true;
> -      }
> -  }
> -
>    template<typename _ElementType, typename _Extents,
>            typename _LayoutPolicy = layout_right,
>            typename _AccessorPolicy = default_accessor<_ElementType>>
> @@ -3056,17 +3042,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         constexpr reference
>         operator[](_OIndexTypes... __indices) const
>         {
> -         auto __checked_call = [this](auto... __idxs) -> index_type
> -           {
> -             if constexpr (sizeof...(__idxs) > 0)
> -               __glibcxx_assert(__mdspan::__is_multi_index(extents(),
> -                 span<const index_type, sizeof...(__idxs)>({__idxs...})));
> -             return _M_mapping(__idxs...);
> -           };
> +         if constexpr (rank() == 0)
> +           return _M_accessor.access(_M_handle, _M_mapping());
> +         else if constexpr (!(is_same_v<_OIndexTypes, index_type> && ...))
> +           return operator[](
> +             
> __mdspan::__index_type_cast<index_type>(std::move(__indices))...);
> +         else
> +          {
> +            auto __is_multi_index = [&]<size_t... 
> _Counts>(index_sequence<_Counts...>)
> +            { return ((__indices < extents().extent(_Counts)) && ...); };
>
> -         auto __index = __checked_call(
> -           static_cast<index_type>(std::move(__indices))...);
> -         return _M_accessor.access(_M_handle, __index);
> +            
> __glibcxx_assert(__is_multi_index(make_index_sequence<rank()>()));
> +            return _M_accessor.access(_M_handle, _M_mapping(__indices...));
> +          }
>         }
>
>        template<typename _OIndexType>
> @@ -3076,7 +3064,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         {
>           auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>)
>             -> reference
> -           { return (*this)[index_type(as_const(__indices[_Counts]))...]; };
> +           {
> +              return operator[](
> +                
> __mdspan::__index_type_cast<index_type>(as_const(__indices[_Counts]))...);
> +           };
>           return __call(make_index_sequence<rank()>());
>         }
>
> @@ -3084,7 +3075,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
>         constexpr reference
>         operator[](const array<_OIndexType, rank()>& __indices) const
> -       { return (*this)[span<const _OIndexType, rank()>(__indices)]; }
> +       { return operator[](span<const _OIndexType, rank()>(__indices)); }
>
>  #if __cplusplus > 202302L
>        template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
> --
> 2.53.0
>

Reply via email to