For the following code: ``` template<bool Const> class IntLike { public: explicit IntLike(int i) : _M_i(i) { } IntLike() = delete; IntLike(const IntLike&) = delete; IntLike(IntLike&&) = delete; const IntLike& operator=(const IntLike&) = delete; const IntLike& operator=(IntLike&&) = delete; constexpr operator int() const noexcept requires (Const) { return _M_i; } constexpr operator int() noexcept requires (!Const) { return _M_i; } private: int _M_i; }; ``` The static assertion fails incorrectly: static_assert(!std::is_constructible_v<std::extents<int, std::dynamic_extent>, std::array<IntLike<false>, 1>>);. It should be eliminated by https://eel.is/c++draft/mdspan.extents#cons-9.1. We emit the ill-formed error from corresponding cosntructor: std::array<IntLike<false>, 1> a1{IntLike<false>(1)}; std::extents<int, std::dynamic_extent> e1(a1); See: https://godbolt.org/z/6GnqnascY
This is due incorrect constrain on corresponding constructor: template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm> requires (_Nm == rank() || _Nm == rank_dynamic()) constexpr explicit(_Nm != rank_dynamic()) extents(span<_OIndexType, _Nm> __exts) noexcept : _M_exts(span<const _OIndexType, _Nm>(__exts)) { } We check `__mdspan::__valid_index_type<_OtherIndex, index_type>`, while we we should check `__mdspan::__valid_index_type<const _OtherIndex&, index_type>`, i.e.: template<typename _OIndexType, size_t _Nm> requires __mdspan::__valid_index_type<const _OIndexType&, index_type> (_Nm == rank() || _Nm == rank_dynamic()) constexpr explicit(_Nm != rank_dynamic()) extents(span<_OIndexType, _Nm> __exts) noexcept : _M_exts(span<const _OIndexType, _Nm>(__exts)) { } Similary for the array constructor, and the constructors of mdspan.
Related to above, the following is ill-formed: ``` class IntLike { public: explicit IntLike(int i) : _M_i(i) { } constexpr operator int() && noexcept { return _M_i; } private: int _M_i; }; IntLike il(1); static_assert(std::is_constructible_v<std::extents<int, std::dynamic_extent>, IntLike>); std::extents<int, std::dynamic_extent> e1(std::move(il)); ``` See: https://godbolt.org/z/hnd6zbde5 This is because, we do not move the index in constructor: template<__mdspan::__valid_index_type<index_type>... _OIndexTypes> requires (sizeof...(_OIndexTypes) == rank() || sizeof...(_OIndexTypes) == rank_dynamic()) constexpr explicit extents(_OIndexTypes... __exts) noexcept : _M_exts(span<const _IndexType, sizeof...(_OIndexTypes)>( initializer_list{_S_storage::_S_int_cast(__exts)...})) { } `__exts` should be moved here, and _S_int_cast needs to be changed to be forwarding. This affects also operators() and mdspan/extents constructors.
The master branch has been updated by Tomasz Kaminski <tkaminsk@gcc.gnu.org>: https://gcc.gnu.org/g:df7beaccef31f19ee73f034eb98e0e47be008d8e commit r16-2325-gdf7beaccef31f19ee73f034eb98e0e47be008d8e Author: Luc Grosheintz <luc.grosheintz@gmail.com> Date: Wed Jul 16 15:45:43 2025 +0200 libstdc++: Refactor mdspan tests [PR121061] PR121061 shows that the test coverage for custom integer types is insufficient. Custom IndexTypes are passed to mdspan related objects in one of two ways: * as a template parameter pack, * or as an array/span. These two cases have different requirements on the (constness of) custom IndexTypes. Therefore, the tests are restructured as follows: * allow testing with different custom integers, * separate code that tests the two cases described above, * use int_like.h for all tests with custom integers. The affected tests are for: * creating extents, layout_stride::mapping and mdspan from custom integers, * mapping::operator() and mdspan::operator[]. PR libstdc++/121061 libstdc++-v3/ChangeLog: * testsuite/23_containers/mdspan/extents/custom_integer.cc: Enable checking with different custom integers. Improve checking non-existence of overloads for incompatible custom integers. * testsuite/23_containers/mdspan/layouts/mapping.cc: ditto. Also improve reuse of int_like.h. * testsuite/23_containers/mdspan/layouts/stride.cc: ditto. * testsuite/23_containers/mdspan/mdspan.cc: ditto. * testsuite/23_containers/mdspan/extents/int_like.h: Rename (old name). * testsuite/23_containers/mdspan/int_like.h: Rename (new name). (ThrowingInt): Add. (NotIntLike): Add. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Reviewed-by: Tomasz KamiÅski <tkaminsk@redhat.com> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
The master branch has been updated by Tomasz Kaminski <tkaminsk@gcc.gnu.org>: https://gcc.gnu.org/g:1eee8430794f790b6d364603685e70d83d8d42f5 commit r16-2327-g1eee8430794f790b6d364603685e70d83d8d42f5 Author: Luc Grosheintz <luc.grosheintz@gmail.com> Date: Wed Jul 16 15:45:44 2025 +0200 libstdc++: Fix constraint for custom integer types in mdspan [PR121061] PR121061 consists of two bugs for mdspan related code. This commit fixes the first one. Namely, when passing custom IndexType as an array or span, the conversion to int must be const. Prior to this commit the constraint incorrectly also allowed non-const conversion. This commit updates all related constraints to check __valid_index_type<const OtherIndexType&, index_type> in those cases. Also adds a MutatingInt to int_like.h which only supports non-const conversion to int and updates the tests. PR libstdc++/121061 libstdc++-v3/ChangeLog: * include/std/mdspan (extents::extents): Fix constraint to prevent non-const conversion to index_type. (layout_stride::mapping::mapping): Ditto. (mdspan::mdspan): Ditto. (mdspan::operator[]): Ditto. * testsuite/23_containers/mdspan/extents/custom_integer.cc: Add test for MutatingInt. * testsuite/23_containers/mdspan/int_like.h (MutatingInt): Add. * testsuite/23_containers/mdspan/layouts/mapping.cc: Add test for MutatingInt. * testsuite/23_containers/mdspan/layouts/stride.cc: Ditto. * testsuite/23_containers/mdspan/mdspan.cc: Ditto. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Reviewed-by: Tomasz KamiÅski <tkaminsk@redhat.com> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
The master branch has been updated by Tomasz Kaminski <tkaminsk@gcc.gnu.org>: https://gcc.gnu.org/g:29d53f6213e0a1569aa8ca9db613b48df642986c commit r16-2328-g29d53f6213e0a1569aa8ca9db613b48df642986c Author: Luc Grosheintz <luc.grosheintz@gmail.com> Date: Wed Jul 16 15:45:45 2025 +0200 libstdc++: Fix forwarding of custom IndexType in mdspan [PR121061] The second bug report in PR121061 is that the conversion of custom OtherIndexType to IndexType is incorrectly not done via r-value references. This commit fixes the forwarding issue, adds a custom IndexType called RValueInt, which only allows conversion to int via r-value reference. PR libstdc++/121061 libstdc++-v3/ChangeLog: * include/std/mdspan (extents::extents): Perform conversion to index_type of an r-value reference. (layout_left::mapping::operator()): Ditto. (layout_right::mapping::operator()): Ditto. (layout_stride::mapping::operator()): Ditto. * testsuite/23_containers/mdspan/extents/custom_integer.cc: Add tests for RValueInt and MutatingInt. * testsuite/23_containers/mdspan/int_like.h (RValueInt): Add. * testsuite/23_containers/mdspan/layouts/mapping.cc: Test with RValueInt. * testsuite/23_containers/mdspan/mdspan.cc: Ditto. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Reviewed-by: Tomasz KamiÅski <tkaminsk@redhat.com> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
Fixed in v16.