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)
{
+ 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