On Tue, Mar 10, 2026 at 4:48 PM Tomasz Kamiński <[email protected]> wrote:
> The _OIndexType template parameter will maybe deduced to reference, when > invoked from constructor and operator[]/at (after r16-7645-g66e60479e97640) > accepting array or span. We need to use forward for class-type and > remove_cvref_t for is_integral checks. > > This resolves LWG4020: extents::index-cast weirdness. > > libstdc++-v3/ChangeLog: > > * include/std/mdspan (__mdspan::__index_type_cast): Handle > forwarding referene and use forward for class types. > * testsuite/23_containers/mdspan/int_like.h (ConstLValueInt) > (CustomIndexKind::ConstLValue): Define. > (CustomIndexType): Handle CustomIndexKind::ConstLValue. > * testsuite/23_containers/mdspan/at.cc: Test with ConstLValueInt. > * testsuite/23_containers/mdspan/extents/custom_integer.cc: > Likewise. > * testsuite/23_containers/mdspan/mdspan.cc: Likewise. > > Signed-off-by: Tomasz Kamiński <[email protected]> > --- > Tested *mdspan* for all standard mode. Testing on x86_64-linux. > OK for trunk when all tests passes? > > libstdc++-v3/include/std/mdspan | 7 ++++--- > libstdc++-v3/testsuite/23_containers/mdspan/at.cc | 1 + > .../23_containers/mdspan/extents/custom_integer.cc | 2 ++ > .../testsuite/23_containers/mdspan/int_like.h | 11 +++++++++++ > libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc | 2 ++ > 5 files changed, 20 insertions(+), 3 deletions(-) > > diff --git a/libstdc++-v3/include/std/mdspan > b/libstdc++-v3/include/std/mdspan > index f8847642c80..5e0d52ff695 100644 > --- a/libstdc++-v3/include/std/mdspan > +++ b/libstdc++-v3/include/std/mdspan > @@ -80,10 +80,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > return true; > } > > - template<typename _IndexType, typename _OIndexType> > + template<typename _IndexType, typename _OIndexTypeRef> > constexpr _IndexType > - __index_type_cast(_OIndexType&& __other) > + __index_type_cast(_OIndexTypeRef&& __other) > { > Locally I have added: // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4020. extents::index-cast weirdnes > + using _OIndexType = std::remove_cvref_t<_OIndexTypeRef>; > if constexpr (std::is_integral_v<_OIndexType>) > { > constexpr _IndexType __index_type_max > @@ -100,7 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > else > { > - auto __ret = static_cast<_IndexType>(std::move(__other)); > + auto __ret = > static_cast<_IndexType>(std::forward<_OIndexTypeRef>(__other)); > if constexpr (std::is_signed_v<_IndexType>) > __glibcxx_assert(__ret >= 0); > return __ret; > diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/at.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/at.cc > index c5a12d12ccc..367398dd078 100644 > --- a/libstdc++-v3/testsuite/23_containers/mdspan/at.cc > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/at.cc > @@ -116,4 +116,5 @@ main() > test_at<ThrowingInt, false, false>(); > test_at<MutatingInt, true, false>(); > test_at<RValueInt, true, false>(); > + test_at<ConstLValueInt, false, true>(); > } > 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 99de4015ef3..4e9669c98d8 100644 > --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc > @@ -86,11 +86,13 @@ main() > test_shape_all<ThrowingInt, false>(); > test_shape_all<MutatingInt, false>(); > test_shape_all<RValueInt, false>(); > + test_shape_all<ConstLValueInt, true>(); > > test_pack_all<int, true>(); > test_pack_all<IntLike, true>(); > test_pack_all<ThrowingInt, false>(); > test_pack_all<MutatingInt, true>(); > test_pack_all<RValueInt, true>(); > + test_pack_all<ConstLValueInt, false>(); > return 0; > } > diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h > b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h > index b839be73ae9..99ecd155ca4 100644 > --- a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h > @@ -7,6 +7,7 @@ enum class CustomIndexKind > Throwing, > Mutating, > RValue, > + ConstLValue, > }; > > template<CustomIndexKind Kind, bool Copyable = false> > @@ -57,6 +58,15 @@ template<CustomIndexKind Kind, bool Copyable = false> > requires (Kind == CustomIndexKind::RValue) > { return value; } > > + constexpr > + operator int() const& noexcept > + requires (Kind == CustomIndexKind::ConstLValue) > + { return value; } > + > + operator int() const&& > + requires (Kind == CustomIndexKind::ConstLValue) > + = delete; > + > private: > int value; > }; > @@ -65,6 +75,7 @@ using IntLike = CustomIndexType<CustomIndexKind::Const>; > using ThrowingInt = CustomIndexType<CustomIndexKind::Throwing>; > using MutatingInt = CustomIndexType<CustomIndexKind::Mutating>; > using RValueInt = CustomIndexType<CustomIndexKind::RValue>; > +using ConstLValueInt = CustomIndexType<CustomIndexKind::ConstLValue>; > > struct NotIntLike > { }; > diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc > index a92a0554417..270b3f18daa 100644 > --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc > @@ -755,6 +755,7 @@ main() > test_from_int_like<ThrowingInt, false, false>(); > test_from_int_like<MutatingInt, true, false>(); > test_from_int_like<RValueInt, true, false>(); > + test_from_int_like<ConstLValueInt, false, true>(); > > test_from_opaque_accessor(); > test_from_base_class_accessor(); > @@ -767,6 +768,7 @@ main() > test_access<ThrowingInt, false, false>(); > test_access<MutatingInt, true, false>(); > test_access<RValueInt, true, false>(); > + test_access<ConstLValueInt, false, true>(); > > test_swap(); > static_assert(test_swap()); > -- > 2.53.0 > >
