https://gcc.gnu.org/g:66e60479e97640d6d73cc3331342cdcc048403e1
commit r16-7645-g66e60479e97640d6d73cc3331342cdcc048403e1 Author: Tomasz Kamiński <[email protected]> Date: Thu Feb 19 13:53:01 2026 +0100 libstdc++: Harmonize mdspan operator[] and at methods. 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. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- 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 a6d2aadcb0cb..f8847642c80e 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>
