[libcxx-commits] [libcxx] [libc++][test] Make `copy_move_types.h` usable in old modes (PR #199183)
A. Jiang via libcxx-commits
libcxx-commits at lists.llvm.org
Fri May 22 01:24:44 PDT 2026
https://github.com/frederick-vs-ja created https://github.com/llvm/llvm-project/pull/199183
This PR makes types in `copy_move_types.h` usable in C++03/11 modes. Because it is discovered that some types in `copy_move_types.h` are useful for testing uninitialized memory algorithms in pre-C++20 modes.
>From ab3b17cae65873724e883ca31a9df06dde87ed5d Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Fri, 22 May 2026 16:20:46 +0800
Subject: [PATCH] [libc++][test] Make `copy_move_types.h` usable in old modes
This PR makes types in `copy_move_types.h` usable in C++03/11 modes.
Because it is discovered that some types in `copy_move_types.h` are
useful for testing uninitialized memory algorithms in pre-C++20 modes.
---
libcxx/test/support/copy_move_types.h | 287 +++++++++++++-------------
1 file changed, 147 insertions(+), 140 deletions(-)
diff --git a/libcxx/test/support/copy_move_types.h b/libcxx/test/support/copy_move_types.h
index dec8d94cac379..1495eb1957633 100644
--- a/libcxx/test/support/copy_move_types.h
+++ b/libcxx/test/support/copy_move_types.h
@@ -10,134 +10,135 @@
#define LIBCXX_TEST_STD_UTILITIES_TUPLE_CNSTR_TYPES_H
#include "test_allocator.h"
+#include "test_macros.h"
#include <type_traits>
#include <tuple>
+#include <utility>
// Types that can be used to test copy/move operations
struct MutableCopy {
int val;
- bool alloc_constructed{false};
+ bool alloc_constructed = false;
- constexpr MutableCopy() = default;
- constexpr MutableCopy(int _val) : val(_val) {}
- constexpr MutableCopy(MutableCopy&) = default;
- constexpr MutableCopy(const MutableCopy&) = delete;
+ MutableCopy() = default;
+ TEST_CONSTEXPR MutableCopy(int _val) : val(_val) {}
+ MutableCopy(MutableCopy&) = default;
+ MutableCopy(const MutableCopy&) = delete;
- constexpr MutableCopy(std::allocator_arg_t, const test_allocator<int>&, MutableCopy& o)
+ TEST_CONSTEXPR MutableCopy(std::allocator_arg_t, const test_allocator<int>&, MutableCopy& o)
: val(o.val), alloc_constructed(true) {}
};
template <>
-struct std::uses_allocator<MutableCopy, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<MutableCopy, test_allocator<int> > : std::true_type {};
struct ConstCopy {
int val;
- bool alloc_constructed{false};
+ bool alloc_constructed = false;
- constexpr ConstCopy() = default;
- constexpr ConstCopy(int _val) : val(_val) {}
- constexpr ConstCopy(const ConstCopy&) = default;
- constexpr ConstCopy(ConstCopy&) = delete;
+ ConstCopy() = default;
+ TEST_CONSTEXPR ConstCopy(int _val) : val(_val) {}
+ ConstCopy(const ConstCopy&) = default;
+ ConstCopy(ConstCopy&) = delete;
- constexpr ConstCopy(std::allocator_arg_t, const test_allocator<int>&, const ConstCopy& o)
+ TEST_CONSTEXPR ConstCopy(std::allocator_arg_t, const test_allocator<int>&, const ConstCopy& o)
: val(o.val), alloc_constructed(true) {}
};
template <>
-struct std::uses_allocator<ConstCopy, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ConstCopy, test_allocator<int> > : std::true_type {};
struct MutableMove {
int val;
- bool alloc_constructed{false};
+ bool alloc_constructed = false;
- constexpr MutableMove() = default;
- constexpr MutableMove(int _val) : val(_val) {}
- constexpr MutableMove(MutableMove&&) = default;
- constexpr MutableMove(const MutableMove&&) = delete;
+ MutableMove() = default;
+ TEST_CONSTEXPR MutableMove(int _val) : val(_val) {}
+ MutableMove(MutableMove&&) = default;
+ MutableMove(const MutableMove&&) = delete;
- constexpr MutableMove(std::allocator_arg_t, const test_allocator<int>&, MutableMove&& o)
+ TEST_CONSTEXPR MutableMove(std::allocator_arg_t, const test_allocator<int>&, MutableMove&& o)
: val(o.val), alloc_constructed(true) {}
};
template <>
-struct std::uses_allocator<MutableMove, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<MutableMove, test_allocator<int> > : std::true_type {};
struct ConstMove {
int val;
- bool alloc_constructed{false};
+ bool alloc_constructed = false;
- constexpr ConstMove() = default;
- constexpr ConstMove(int _val) : val(_val) {}
- constexpr ConstMove(const ConstMove&& o) : val(o.val) {}
- constexpr ConstMove(ConstMove&&) = delete;
+ ConstMove() = default;
+ TEST_CONSTEXPR ConstMove(int _val) : val(_val) {}
+ TEST_CONSTEXPR ConstMove(const ConstMove&& o) : val(o.val) {}
+ ConstMove(ConstMove&&) = delete;
- constexpr ConstMove(std::allocator_arg_t, const test_allocator<int>&, const ConstMove&& o)
+ TEST_CONSTEXPR ConstMove(std::allocator_arg_t, const test_allocator<int>&, const ConstMove&& o)
: val(o.val), alloc_constructed(true) {}
};
template <>
-struct std::uses_allocator<ConstMove, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ConstMove, test_allocator<int> > : std::true_type {};
template <class T>
struct ConvertibleFrom {
T v;
- bool alloc_constructed{false};
-
- constexpr ConvertibleFrom() = default;
- constexpr ConvertibleFrom(T& _v)
- requires(std::is_constructible_v<T, T&>)
- : v(_v) {}
- constexpr ConvertibleFrom(const T& _v)
- requires(std::is_constructible_v<T, const T&> && !std::is_const_v<T>)
- : v(_v) {}
- constexpr ConvertibleFrom(T&& _v)
- requires(std::is_constructible_v<T, T &&>)
- : v(std::move(_v)) {}
- constexpr ConvertibleFrom(const T&& _v)
- requires(std::is_constructible_v<T, const T &&> && !std::is_const_v<T>)
- : v(std::move(_v)) {}
-
- template <class U>
- requires std::is_constructible_v<ConvertibleFrom, U&&>
- constexpr ConvertibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
- : ConvertibleFrom{std::forward<U>(_u)} {
+ bool alloc_constructed = false;
+
+ ConvertibleFrom() = default;
+ template <class U = T, typename std::enable_if<std::is_constructible<U, U&>::value, int>::type = 0>
+ TEST_CONSTEXPR ConvertibleFrom(T& _v) : v(_v) {}
+ template <
+ class U = T,
+ typename std::enable_if<std::is_constructible<U, const U&>::value && !std::is_const<U>::value, int>::type = 0>
+ TEST_CONSTEXPR ConvertibleFrom(const T& _v) : v(_v) {}
+ template <class U = T, typename std::enable_if<std::is_constructible<U, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 ConvertibleFrom(T&& _v) : v(std::move(_v)) {}
+ template <
+ class U = T,
+ typename std::enable_if<std::is_constructible<U, const U&&>::value && !std::is_const<U>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 ConvertibleFrom(const T&& _v) : v(std::move(_v)) {}
+
+ template <class U, typename std::enable_if<std::is_constructible<ConvertibleFrom, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 ConvertibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
+ : ConvertibleFrom(std::forward<U>(_u)) {
alloc_constructed = true;
}
};
template <class T>
-struct std::uses_allocator<ConvertibleFrom<T>, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ConvertibleFrom<T>, test_allocator<int> > : std::true_type {};
template <class T>
struct ExplicitConstructibleFrom {
T v;
- bool alloc_constructed{false};
-
- constexpr explicit ExplicitConstructibleFrom() = default;
- constexpr explicit ExplicitConstructibleFrom(T& _v)
- requires(std::is_constructible_v<T, T&>)
- : v(_v) {}
- constexpr explicit ExplicitConstructibleFrom(const T& _v)
- requires(std::is_constructible_v<T, const T&> && !std::is_const_v<T>)
- : v(_v) {}
- constexpr explicit ExplicitConstructibleFrom(T&& _v)
- requires(std::is_constructible_v<T, T &&>)
- : v(std::move(_v)) {}
- constexpr explicit ExplicitConstructibleFrom(const T&& _v)
- requires(std::is_constructible_v<T, const T &&> && !std::is_const_v<T>)
- : v(std::move(_v)) {}
-
- template <class U>
- requires std::is_constructible_v<ExplicitConstructibleFrom, U&&>
- constexpr ExplicitConstructibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
- : ExplicitConstructibleFrom{std::forward<U>(_u)} {
+ bool alloc_constructed = false;
+
+ explicit ExplicitConstructibleFrom() = default;
+ template <class U = T, typename std::enable_if<std::is_constructible<U, U&>::value, int>::type = 0>
+ TEST_CONSTEXPR explicit ExplicitConstructibleFrom(T& _v) : v(_v) {}
+ template <
+ class U = T,
+ typename std::enable_if<std::is_constructible<U, const U&>::value && !std::is_const<U>::value, int>::type = 0>
+ TEST_CONSTEXPR explicit ExplicitConstructibleFrom(const T& _v) : v(_v) {}
+ template <class U = T, typename std::enable_if<std::is_constructible<U, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 explicit ExplicitConstructibleFrom(T&& _v) : v(std::move(_v)) {}
+ template <
+ class U = T,
+ typename std::enable_if<std::is_constructible<U, const U&&>::value && !std::is_const<U>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 explicit ExplicitConstructibleFrom(const T&& _v) : v(std::move(_v)) {}
+
+ template <class U,
+ typename std::enable_if<std::is_constructible<ExplicitConstructibleFrom, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 ExplicitConstructibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
+ : ExplicitConstructibleFrom(std::forward<U>(_u)) {
alloc_constructed = true;
}
};
template <class T>
-struct std::uses_allocator<ExplicitConstructibleFrom<T>, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ExplicitConstructibleFrom<T>, test_allocator<int> > : std::true_type {};
struct TracedCopyMove {
int nonConstCopy = 0;
@@ -146,172 +147,178 @@ struct TracedCopyMove {
int constMove = 0;
bool alloc_constructed = false;
- constexpr TracedCopyMove() = default;
- constexpr TracedCopyMove(const TracedCopyMove& other)
- : nonConstCopy(other.nonConstCopy), constCopy(other.constCopy + 1), nonConstMove(other.nonConstMove),
+ TracedCopyMove() = default;
+ TEST_CONSTEXPR TracedCopyMove(const TracedCopyMove& other)
+ : nonConstCopy(other.nonConstCopy),
+ constCopy(other.constCopy + 1),
+ nonConstMove(other.nonConstMove),
constMove(other.constMove) {}
- constexpr TracedCopyMove(TracedCopyMove& other)
- : nonConstCopy(other.nonConstCopy + 1), constCopy(other.constCopy), nonConstMove(other.nonConstMove),
+ TEST_CONSTEXPR TracedCopyMove(TracedCopyMove& other)
+ : nonConstCopy(other.nonConstCopy + 1),
+ constCopy(other.constCopy),
+ nonConstMove(other.nonConstMove),
constMove(other.constMove) {}
- constexpr TracedCopyMove(TracedCopyMove&& other)
- : nonConstCopy(other.nonConstCopy), constCopy(other.constCopy), nonConstMove(other.nonConstMove + 1),
+ TEST_CONSTEXPR TracedCopyMove(TracedCopyMove&& other)
+ : nonConstCopy(other.nonConstCopy),
+ constCopy(other.constCopy),
+ nonConstMove(other.nonConstMove + 1),
constMove(other.constMove) {}
- constexpr TracedCopyMove(const TracedCopyMove&& other)
- : nonConstCopy(other.nonConstCopy), constCopy(other.constCopy), nonConstMove(other.nonConstMove),
+ TEST_CONSTEXPR TracedCopyMove(const TracedCopyMove&& other)
+ : nonConstCopy(other.nonConstCopy),
+ constCopy(other.constCopy),
+ nonConstMove(other.nonConstMove),
constMove(other.constMove + 1) {}
- template <class U>
- requires std::is_constructible_v<TracedCopyMove, U&&>
- constexpr TracedCopyMove(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
- : TracedCopyMove{std::forward<U>(_u)} {
+ template <class U, typename std::enable_if<std::is_constructible<TracedCopyMove, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 TracedCopyMove(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
+ : TracedCopyMove(std::forward<U>(_u)) {
alloc_constructed = true;
}
};
template <>
-struct std::uses_allocator<TracedCopyMove, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<TracedCopyMove, test_allocator<int> > : std::true_type {};
// If the constructor tuple(tuple<UTypes...>&) is not available,
// the fallback call to `tuple(const tuple&) = default;` or any other
// constructor that takes const ref would increment the constCopy.
-inline constexpr bool nonConstCopyCtrCalled(const TracedCopyMove& obj) {
+inline TEST_CONSTEXPR bool nonConstCopyCtrCalled(const TracedCopyMove& obj) {
return obj.nonConstCopy == 1 && obj.constCopy == 0 && obj.constMove == 0 && obj.nonConstMove == 0;
}
// If the constructor tuple(const tuple<UTypes...>&&) is not available,
// the fallback call to `tuple(const tuple&) = default;` or any other
// constructor that takes const ref would increment the constCopy.
-inline constexpr bool constMoveCtrCalled(const TracedCopyMove& obj) {
+inline TEST_CONSTEXPR bool constMoveCtrCalled(const TracedCopyMove& obj) {
return obj.nonConstMove == 0 && obj.constMove == 1 && obj.constCopy == 0 && obj.nonConstCopy == 0;
}
struct NoConstructorFromInt {};
+#if TEST_STD_VER >= 11
struct CvtFromTupleRef : TracedCopyMove {
- constexpr CvtFromTupleRef() = default;
- constexpr CvtFromTupleRef(std::tuple<CvtFromTupleRef>& other)
+ CvtFromTupleRef() = default;
+ TEST_CONSTEXPR_CXX14 CvtFromTupleRef(std::tuple<CvtFromTupleRef>& other)
: TracedCopyMove(static_cast<TracedCopyMove&>(std::get<0>(other))) {}
};
struct ExplicitCtrFromTupleRef : TracedCopyMove {
- constexpr explicit ExplicitCtrFromTupleRef() = default;
- constexpr explicit ExplicitCtrFromTupleRef(std::tuple<ExplicitCtrFromTupleRef>& other)
+ explicit ExplicitCtrFromTupleRef() = default;
+ TEST_CONSTEXPR_CXX14 explicit ExplicitCtrFromTupleRef(std::tuple<ExplicitCtrFromTupleRef>& other)
: TracedCopyMove(static_cast<TracedCopyMove&>(std::get<0>(other))) {}
};
struct CvtFromConstTupleRefRef : TracedCopyMove {
- constexpr CvtFromConstTupleRefRef() = default;
- constexpr CvtFromConstTupleRefRef(const std::tuple<CvtFromConstTupleRefRef>&& other)
+ CvtFromConstTupleRefRef() = default;
+ TEST_CONSTEXPR_CXX14 CvtFromConstTupleRefRef(const std::tuple<CvtFromConstTupleRefRef>&& other)
: TracedCopyMove(static_cast<const TracedCopyMove&&>(std::get<0>(other))) {}
};
struct ExplicitCtrFromConstTupleRefRef : TracedCopyMove {
- constexpr explicit ExplicitCtrFromConstTupleRefRef() = default;
- constexpr explicit ExplicitCtrFromConstTupleRefRef(std::tuple<const ExplicitCtrFromConstTupleRefRef>&& other)
+ explicit ExplicitCtrFromConstTupleRefRef() = default;
+ TEST_CONSTEXPR_CXX14 explicit ExplicitCtrFromConstTupleRefRef(
+ std::tuple<const ExplicitCtrFromConstTupleRefRef>&& other)
: TracedCopyMove(static_cast<const TracedCopyMove&&>(std::get<0>(other))) {}
};
+#endif
+#if TEST_STD_VER >= 20
template <class T>
void conversion_test(T);
template <class T, class... Args>
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+#endif
struct CopyAssign {
int val;
- constexpr CopyAssign() = default;
- constexpr CopyAssign(int v) : val(v) {}
+ CopyAssign() = default;
+ TEST_CONSTEXPR CopyAssign(int v) : val(v) {}
- constexpr CopyAssign& operator=(const CopyAssign&) = default;
+ CopyAssign& operator=(const CopyAssign&) = default;
- constexpr const CopyAssign& operator=(const CopyAssign&) const = delete;
- constexpr CopyAssign& operator=(CopyAssign&&) = delete;
- constexpr const CopyAssign& operator=(CopyAssign&&) const = delete;
+ const CopyAssign& operator=(const CopyAssign&) const = delete;
+ CopyAssign& operator=(CopyAssign&&) = delete;
+ const CopyAssign& operator=(CopyAssign&&) const = delete;
};
struct ConstCopyAssign {
mutable int val;
- constexpr ConstCopyAssign() = default;
- constexpr ConstCopyAssign(int v) : val(v) {}
+ ConstCopyAssign() = default;
+ TEST_CONSTEXPR ConstCopyAssign(int v) : val(v) {}
- constexpr const ConstCopyAssign& operator=(const ConstCopyAssign& other) const {
+ TEST_CONSTEXPR_CXX14 const ConstCopyAssign& operator=(const ConstCopyAssign& other) const {
val = other.val;
return *this;
}
- constexpr ConstCopyAssign& operator=(const ConstCopyAssign&) = delete;
- constexpr ConstCopyAssign& operator=(ConstCopyAssign&&) = delete;
- constexpr const ConstCopyAssign& operator=(ConstCopyAssign&&) const = delete;
+ ConstCopyAssign& operator=(const ConstCopyAssign&) = delete;
+ ConstCopyAssign& operator=(ConstCopyAssign&&) = delete;
+ const ConstCopyAssign& operator=(ConstCopyAssign&&) const = delete;
};
struct MoveAssign {
int val;
- constexpr MoveAssign() = default;
- constexpr MoveAssign(int v) : val(v) {}
+ MoveAssign() = default;
+ TEST_CONSTEXPR MoveAssign(int v) : val(v) {}
- constexpr MoveAssign& operator=(MoveAssign&&) = default;
+ MoveAssign& operator=(MoveAssign&&) = default;
- constexpr MoveAssign& operator=(const MoveAssign&) = delete;
- constexpr const MoveAssign& operator=(const MoveAssign&) const = delete;
- constexpr const MoveAssign& operator=(MoveAssign&&) const = delete;
+ MoveAssign& operator=(const MoveAssign&) = delete;
+ const MoveAssign& operator=(const MoveAssign&) const = delete;
+ const MoveAssign& operator=(MoveAssign&&) const = delete;
};
struct ConstMoveAssign {
mutable int val;
- constexpr ConstMoveAssign() = default;
- constexpr ConstMoveAssign(int v) : val(v) {}
+ ConstMoveAssign() = default;
+ TEST_CONSTEXPR ConstMoveAssign(int v) : val(v) {}
- constexpr const ConstMoveAssign& operator=(ConstMoveAssign&& other) const {
+ TEST_CONSTEXPR_CXX14 const ConstMoveAssign& operator=(ConstMoveAssign&& other) const {
val = other.val;
return *this;
}
- constexpr ConstMoveAssign& operator=(const ConstMoveAssign&) = delete;
- constexpr const ConstMoveAssign& operator=(const ConstMoveAssign&) const = delete;
- constexpr ConstMoveAssign& operator=(ConstMoveAssign&&) = delete;
+ ConstMoveAssign& operator=(const ConstMoveAssign&) = delete;
+ const ConstMoveAssign& operator=(const ConstMoveAssign&) const = delete;
+ ConstMoveAssign& operator=(ConstMoveAssign&&) = delete;
};
template <class T>
struct AssignableFrom {
T v;
- constexpr AssignableFrom() = default;
+ AssignableFrom() = default;
- template <class U>
- constexpr AssignableFrom(U&& u)
- requires std::is_constructible_v<T, U&&>
- : v(std::forward<U>(u)) {}
+ template <class U, typename std::enable_if<std::is_constructible<T, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 AssignableFrom(U&& u) : v(std::forward<U>(u)) {}
- constexpr AssignableFrom& operator=(const T& t)
- requires std::is_copy_assignable_v<T>
- {
+ template <class U = T, typename std::enable_if<std::is_copy_assignable<U>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 AssignableFrom& operator=(const T& t) {
v = t;
return *this;
}
- constexpr AssignableFrom& operator=(T&& t)
- requires std::is_move_assignable_v<T>
- {
+ template <class U = T, typename std::enable_if<std::is_move_assignable<U>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 AssignableFrom& operator=(T&& t) {
v = std::move(t);
return *this;
}
- constexpr const AssignableFrom& operator=(const T& t) const
- requires std::is_assignable_v<const T&, const T&>
- {
+ template <class U = T, typename std::enable_if<std::is_assignable<const U&, const U&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 const AssignableFrom& operator=(const T& t) const {
v = t;
return *this;
}
- constexpr const AssignableFrom& operator=(T&& t) const
- requires std::is_assignable_v<const T&, T&&>
- {
+ template <class U = T, typename std::enable_if<std::is_assignable<const U&, U&&>::value, int>::type = 0>
+ TEST_CONSTEXPR_CXX14 const AssignableFrom& operator=(T&& t) const {
v = std::move(t);
return *this;
}
@@ -323,21 +330,21 @@ struct TracedAssignment {
int moveAssign = 0;
mutable int constMoveAssign = 0;
- constexpr TracedAssignment() = default;
+ TracedAssignment() = default;
- constexpr TracedAssignment& operator=(const TracedAssignment&) {
+ TEST_CONSTEXPR_CXX14 TracedAssignment& operator=(const TracedAssignment&) {
copyAssign++;
return *this;
}
- constexpr const TracedAssignment& operator=(const TracedAssignment&) const {
+ TEST_CONSTEXPR_CXX14 const TracedAssignment& operator=(const TracedAssignment&) const {
constCopyAssign++;
return *this;
}
- constexpr TracedAssignment& operator=(TracedAssignment&&) {
+ TEST_CONSTEXPR_CXX14 TracedAssignment& operator=(TracedAssignment&&) {
moveAssign++;
return *this;
}
- constexpr const TracedAssignment& operator=(TracedAssignment&&) const {
+ TEST_CONSTEXPR_CXX14 const TracedAssignment& operator=(TracedAssignment&&) const {
constMoveAssign++;
return *this;
}
More information about the libcxx-commits
mailing list