[PATCH v1 2/3] libstdc++: Fix constraint for custom integer types in mdspan [PR121061]
Tomasz Kaminski
tkaminsk@redhat.com
Thu Jul 17 14:14:28 GMT 2025
This shows how useful refactoring for a test was. Thanks for posting.
Just merged to master.
On Wed, Jul 16, 2025 at 10:05 PM Jonathan Wakely <jwakely.gcc@gmail.com>
wrote:
>
>
> On Wed, 16 Jul 2025, 14:46 Luc Grosheintz, <luc.grosheintz@gmail.com>
> wrote:
>
>> 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.
>>
>
> OK for trunk
>
>
>> 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.
>>
>> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
>> ---
>> libstdc++-v3/include/std/mdspan | 34 +++++++++++--------
>> .../mdspan/extents/custom_integer.cc | 1 +
>> .../testsuite/23_containers/mdspan/int_like.h | 7 ++++
>> .../23_containers/mdspan/layouts/mapping.cc | 3 ++
>> .../23_containers/mdspan/layouts/stride.cc | 1 +
>> .../testsuite/23_containers/mdspan/mdspan.cc | 2 ++
>> 6 files changed, 34 insertions(+), 14 deletions(-)
>>
>> diff --git a/libstdc++-v3/include/std/mdspan
>> b/libstdc++-v3/include/std/mdspan
>> index b34116a85e6..930997e9536 100644
>> --- a/libstdc++-v3/include/std/mdspan
>> +++ b/libstdc++-v3/include/std/mdspan
>> @@ -288,15 +288,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> initializer_list{_S_storage::_S_int_cast(__exts)...}))
>> { }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType,
>> size_t _Nm>
>> - requires (_Nm == rank() || _Nm == rank_dynamic())
>> + 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))
>> { }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType,
>> size_t _Nm>
>> - requires (_Nm == rank() || _Nm == rank_dynamic())
>> + 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(const array<_OIndexType, _Nm>& __exts) noexcept
>> : _M_exts(span<const _OIndexType, _Nm>(__exts))
>> @@ -878,7 +880,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> constexpr
>> mapping(const mapping&) noexcept = default;
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType>
>> + template<typename _OIndexType>
>> + requires __mdspan::__valid_index_type<const _OIndexType&,
>> index_type>
>> constexpr
>> mapping(const extents_type& __exts,
>> span<_OIndexType, extents_type::rank()> __strides)
>> noexcept
>> @@ -888,7 +891,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> _M_strides[__i] = index_type(as_const(__strides[__i]));
>> }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType>
>> + template<typename _OIndexType>
>> + requires __mdspan::__valid_index_type<const _OIndexType&,
>> index_type>
>> constexpr
>> mapping(const extents_type& __exts,
>> const array<_OIndexType, extents_type::rank()>& __strides)
>> @@ -1134,9 +1138,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> _M_handle(std::move(__handle))
>> { }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType,
>> - size_t _Nm>
>> - requires (_Nm == rank() || _Nm == rank_dynamic())
>> + template<typename _OIndexType, size_t _Nm>
>> + requires __mdspan::__valid_index_type<const _OIndexType&,
>> index_type>
>> + && (_Nm == rank() || _Nm == rank_dynamic())
>> && is_constructible_v<mapping_type, extents_type>
>> && is_default_constructible_v<accessor_type>
>> constexpr explicit(_Nm != rank_dynamic())
>> @@ -1145,9 +1149,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> _M_handle(std::move(__handle))
>> { }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType,
>> - size_t _Nm>
>> - requires (_Nm == rank() || _Nm == rank_dynamic())
>> + template<typename _OIndexType, size_t _Nm>
>> + requires __mdspan::__valid_index_type<const _OIndexType&,
>> index_type>
>> + && (_Nm == rank() || _Nm == rank_dynamic())
>> && is_constructible_v<mapping_type, extents_type>
>> && is_default_constructible_v<accessor_type>
>> constexpr explicit(_Nm != rank_dynamic())
>> @@ -1218,7 +1222,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> return _M_accessor.access(_M_handle, __index);
>> }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType>
>> + template<typename _OIndexType>
>> + requires __mdspan::__valid_index_type<const _OIndexType&,
>> index_type>
>> constexpr reference
>> operator[](span<_OIndexType, rank()> __indices) const
>> {
>> @@ -1228,7 +1233,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> return __call(make_index_sequence<rank()>());
>> }
>>
>> - template<__mdspan::__valid_index_type<index_type> _OIndexType>
>> + template<typename _OIndexType>
>> + 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)]; }
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> index 4f631815b10..92c2ebb46e1 100644
>> ---
>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> +++
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> @@ -84,6 +84,7 @@ main()
>> test_shape_all<int, true>();
>> test_shape_all<IntLike, true>();
>> test_shape_all<ThrowingInt, false>();
>> + test_shape_all<MutatingInt, false>();
>>
>> test_pack_all<int, true>();
>> test_pack_all<IntLike, true>();
>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> index ed45375f986..f4f4a773193 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> @@ -5,6 +5,7 @@ enum class CustomIndexKind
>> {
>> Const,
>> Throwing,
>> + Mutating,
>> };
>>
>> template<CustomIndexKind Kind>
>> @@ -36,12 +37,18 @@ template<CustomIndexKind Kind>
>> requires (Kind == CustomIndexKind::Throwing)
>> { return _M_i; }
>>
>> + constexpr
>> + operator int() noexcept
>> + requires (Kind == CustomIndexKind::Mutating)
>> + { return _M_i; }
>> +
>> private:
>> int _M_i;
>> };
>>
>> using IntLike = CustomIndexType<CustomIndexKind::Const>;
>> using ThrowingInt = CustomIndexType<CustomIndexKind::Throwing>;
>> +using MutatingInt = CustomIndexType<CustomIndexKind::Mutating>;
>>
>> struct NotIntLike
>> { };
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> index 17f0c00acf2..6742fa11a51 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> @@ -180,6 +180,7 @@ template<typename Layout>
>> static_assert(has_linear_index<Mapping, int>);
>> static_assert(has_linear_index<Mapping, double>);
>> static_assert(has_linear_index<Mapping, IntLike>);
>> + static_assert(has_linear_index<Mapping, MutatingInt>);
>> static_assert(!has_linear_index<Mapping, ThrowingInt>);
>> static_assert(!has_linear_index<Mapping, NotIntLike>);
>> static_assert(!has_linear_index<Mapping, int, int>);
>> @@ -194,6 +195,7 @@ template<typename Layout>
>> static_assert(has_linear_index<Mapping, int, int>);
>> static_assert(has_linear_index<Mapping, double, double>);
>> static_assert(has_linear_index<Mapping, IntLike, int>);
>> + static_assert(has_linear_index<Mapping, MutatingInt, int>);
>> static_assert(!has_linear_index<Mapping, ThrowingInt, int>);
>> static_assert(!has_linear_index<Mapping, NotIntLike, int>);
>> static_assert(!has_linear_index<Mapping, int, int, int>);
>> @@ -524,6 +526,7 @@ template<typename Layout>
>> if !consteval
>> {
>> test_linear_index_all<Layout, IntLike>();
>> + test_linear_index_all<Layout, MutatingInt>();
>> }
>>
>> test_required_span_size_all<Layout>();
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> index 1267306fb5c..8d2fad2936f 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> @@ -65,6 +65,7 @@ test_stride_constructible_all()
>> test_stride_constructible<E0, E0, int, 0, true>();
>> test_stride_constructible<E0, E0, IntLike, 0, true>();
>> test_stride_constructible<E0, E0, ThrowingInt, 0, false>();
>> + test_stride_constructible<E0, E0, MutatingInt, 0, false>();
>> test_stride_constructible<E0, E0, NotIntLike, 0, false>();
>> test_stride_constructible<E1, E1, int, 1, true>();
>> test_stride_constructible<E2, E1, int, 1, true>();
>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> index adabb0c6639..22ec68ea2d1 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> @@ -693,6 +693,7 @@ main()
>> static_assert(test_from_int_like<int, true, true>());
>> test_from_int_like<IntLike, true, true>();
>> test_from_int_like<ThrowingInt, false, false>();
>> + test_from_int_like<MutatingInt, true, false>();
>>
>> test_from_opaque_accessor();
>> test_from_base_class_accessor();
>> @@ -703,6 +704,7 @@ main()
>> static_assert(test_access<int, true, true>());
>> test_access<IntLike, true, true>();
>> test_access<ThrowingInt, false, false>();
>> + test_access<MutatingInt, true, false>();
>>
>> test_swap();
>> static_assert(test_swap());
>> --
>> 2.50.0
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250717/70006446/attachment-0001.htm>
More information about the Libstdc++
mailing list