summaryrefslogtreecommitdiff
path: root/absl/meta/type_traits_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/meta/type_traits_test.cc')
-rw-r--r--absl/meta/type_traits_test.cc425
1 files changed, 418 insertions, 7 deletions
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index f51f5ded..a7a9c5c9 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -214,6 +214,29 @@ class DeletedDefaultCtor {
int n_;
};
+class TrivialMoveCtor {
+ public:
+ explicit TrivialMoveCtor(int n) : n_(n) {}
+ TrivialMoveCtor(TrivialMoveCtor&&) = default;
+ TrivialMoveCtor& operator=(const TrivialMoveCtor& t) {
+ n_ = t.n_;
+ return *this;
+ }
+
+ private:
+ int n_;
+};
+
+class NontrivialMoveCtor {
+ public:
+ explicit NontrivialMoveCtor(int n) : n_(n) {}
+ NontrivialMoveCtor(NontrivialMoveCtor&& t) noexcept : n_(t.n_) {}
+ NontrivialMoveCtor& operator=(const NontrivialMoveCtor&) = default;
+
+ private:
+ int n_;
+};
+
class TrivialCopyCtor {
public:
explicit TrivialCopyCtor(int n) : n_(n) {}
@@ -247,6 +270,29 @@ class DeletedCopyCtor {
int n_;
};
+class TrivialMoveAssign {
+ public:
+ explicit TrivialMoveAssign(int n) : n_(n) {}
+ TrivialMoveAssign(const TrivialMoveAssign& t) : n_(t.n_) {}
+ TrivialMoveAssign& operator=(TrivialMoveAssign&&) = default;
+ ~TrivialMoveAssign() {} // can have nontrivial destructor
+ private:
+ int n_;
+};
+
+class NontrivialMoveAssign {
+ public:
+ explicit NontrivialMoveAssign(int n) : n_(n) {}
+ NontrivialMoveAssign(const NontrivialMoveAssign&) = default;
+ NontrivialMoveAssign& operator=(NontrivialMoveAssign&& t) noexcept {
+ n_ = t.n_;
+ return *this;
+ }
+
+ private:
+ int n_;
+};
+
class TrivialCopyAssign {
public:
explicit TrivialCopyAssign(int n) : n_(n) {}
@@ -280,10 +326,20 @@ class DeletedCopyAssign {
int n_;
};
-struct NonCopyable {
- NonCopyable() = default;
- NonCopyable(const NonCopyable&) = delete;
- NonCopyable& operator=(const NonCopyable&) = delete;
+struct MovableNonCopyable {
+ MovableNonCopyable() = default;
+ MovableNonCopyable(const MovableNonCopyable&) = delete;
+ MovableNonCopyable(MovableNonCopyable&&) = default;
+ MovableNonCopyable& operator=(const MovableNonCopyable&) = delete;
+ MovableNonCopyable& operator=(MovableNonCopyable&&) = default;
+};
+
+struct NonCopyableOrMovable {
+ NonCopyableOrMovable() = default;
+ NonCopyableOrMovable(const NonCopyableOrMovable&) = delete;
+ NonCopyableOrMovable(NonCopyableOrMovable&&) = delete;
+ NonCopyableOrMovable& operator=(const NonCopyableOrMovable&) = delete;
+ NonCopyableOrMovable& operator=(NonCopyableOrMovable&&) = delete;
};
class Base {
@@ -329,6 +385,22 @@ class Base {
#define ABSL_GCC_BUG_TRIVIALLY_CONSTRUCTIBLE_ON_ARRAY_OF_NONTRIVIAL 1
#endif
+TEST(TypeTraitsTest, TestIsFunction) {
+ struct Callable {
+ void operator()() {}
+ };
+ EXPECT_TRUE(absl::is_function<void()>::value);
+ EXPECT_TRUE(absl::is_function<void()&>::value);
+ EXPECT_TRUE(absl::is_function<void() const>::value);
+ EXPECT_TRUE(absl::is_function<void() noexcept>::value);
+ EXPECT_TRUE(absl::is_function<void(...) noexcept>::value);
+
+ EXPECT_FALSE(absl::is_function<void(*)()>::value);
+ EXPECT_FALSE(absl::is_function<void(&)()>::value);
+ EXPECT_FALSE(absl::is_function<int>::value);
+ EXPECT_FALSE(absl::is_function<Callable>::value);
+}
+
TEST(TypeTraitsTest, TestTrivialDestructor) {
// Verify that arithmetic types and pointers have trivial destructors.
EXPECT_TRUE(absl::is_trivially_destructible<bool>::value);
@@ -474,6 +546,79 @@ TEST(TypeTraitsTest, TestTrivialDefaultCtor) {
#endif
}
+TEST(TypeTraitsTest, TestTrivialMoveCtor) {
+ // Verify that arithmetic types and pointers have trivial move
+ // constructors.
+ EXPECT_TRUE(absl::is_trivially_move_constructible<bool>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<signed char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<wchar_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<uint16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<uint64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<float>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<long double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<const std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<const Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<std::string**>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial**>::value);
+
+ // Reference types
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int&>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int&&>::value);
+
+ // types with compiler generated move ctors
+ EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<TrivialMoveCtor>::value);
+
+ // Verify that types without them (i.e. nontrivial or deleted) are not.
+ EXPECT_FALSE(
+ absl::is_trivially_move_constructible<NontrivialCopyCtor>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<DeletedCopyCtor>::value);
+ EXPECT_FALSE(
+ absl::is_trivially_move_constructible<NonCopyableOrMovable>::value);
+
+#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
+ // type with nontrivial destructor are nontrivial move construbtible
+ EXPECT_FALSE(
+ absl::is_trivially_move_constructible<NontrivialDestructor>::value);
+#endif
+
+ // types with vtables
+ EXPECT_FALSE(absl::is_trivially_move_constructible<Base>::value);
+
+ // Verify that simple_pair of such types is trivially move constructible
+ EXPECT_TRUE(
+ (absl::is_trivially_move_constructible<simple_pair<int, char*>>::value));
+ EXPECT_TRUE((
+ absl::is_trivially_move_constructible<simple_pair<int, Trivial>>::value));
+ EXPECT_TRUE((absl::is_trivially_move_constructible<
+ simple_pair<int, TrivialMoveCtor>>::value));
+
+ // Verify that types without trivial move constructors are
+ // correctly marked as such.
+ EXPECT_FALSE(absl::is_trivially_move_constructible<std::string>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<std::vector<int>>::value);
+
+ // Verify that simple_pairs of types without trivial move constructors
+ // are not marked as trivial.
+ EXPECT_FALSE((absl::is_trivially_move_constructible<
+ simple_pair<int, std::string>>::value));
+ EXPECT_FALSE((absl::is_trivially_move_constructible<
+ simple_pair<std::string, int>>::value));
+
+ // Verify that arrays are not
+ using int10 = int[10];
+ EXPECT_FALSE(absl::is_trivially_move_constructible<int10>::value);
+}
+
TEST(TypeTraitsTest, TestTrivialCopyCtor) {
// Verify that arithmetic types and pointers have trivial copy
// constructors.
@@ -498,6 +643,10 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
EXPECT_TRUE(absl::is_trivially_copy_constructible<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial**>::value);
+ // Reference types
+ EXPECT_TRUE(absl::is_trivially_copy_constructible<int&>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_constructible<int&&>::value);
+
// types with compiler generated copy ctors
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivialCopyCtor>::value);
@@ -507,7 +656,9 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
absl::is_trivially_copy_constructible<NontrivialCopyCtor>::value);
EXPECT_FALSE(absl::is_trivially_copy_constructible<DeletedCopyCtor>::value);
EXPECT_FALSE(
- absl::is_trivially_copy_constructible<NonCopyable>::value);
+ absl::is_trivially_copy_constructible<MovableNonCopyable>::value);
+ EXPECT_FALSE(
+ absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value);
#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
// type with nontrivial destructor are nontrivial copy construbtible
@@ -543,6 +694,74 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
EXPECT_FALSE(absl::is_trivially_copy_constructible<int10>::value);
}
+TEST(TypeTraitsTest, TestTrivialMoveAssign) {
+ // Verify that arithmetic types and pointers have trivial move
+ // assignment operators.
+ EXPECT_TRUE(absl::is_trivially_move_assignable<bool>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<signed char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<wchar_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<int16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<uint16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<int64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<uint64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<float>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<long double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<const std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<const Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<std::string**>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial**>::value);
+
+ // const qualified types are not assignable
+ EXPECT_FALSE(absl::is_trivially_move_assignable<const int>::value);
+
+ // types with compiler generated move assignment
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<TrivialMoveAssign>::value);
+
+ // Verify that types without them (i.e. nontrivial or deleted) are not.
+ EXPECT_FALSE(absl::is_trivially_move_assignable<NontrivialCopyAssign>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<DeletedCopyAssign>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<NonCopyableOrMovable>::value);
+
+ // types with vtables
+ EXPECT_FALSE(absl::is_trivially_move_assignable<Base>::value);
+
+ // Verify that simple_pair is trivially assignable
+ EXPECT_TRUE(
+ (absl::is_trivially_move_assignable<simple_pair<int, char*>>::value));
+ EXPECT_TRUE(
+ (absl::is_trivially_move_assignable<simple_pair<int, Trivial>>::value));
+ EXPECT_TRUE((absl::is_trivially_move_assignable<
+ simple_pair<int, TrivialMoveAssign>>::value));
+
+ // Verify that types not trivially move assignable are
+ // correctly marked as such.
+ EXPECT_FALSE(absl::is_trivially_move_assignable<std::string>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<std::vector<int>>::value);
+
+ // Verify that simple_pairs of types not trivially move assignable
+ // are not marked as trivial.
+ EXPECT_FALSE((absl::is_trivially_move_assignable<
+ simple_pair<int, std::string>>::value));
+ EXPECT_FALSE((absl::is_trivially_move_assignable<
+ simple_pair<std::string, int>>::value));
+
+ // Verify that arrays are not trivially move assignable
+ using int10 = int[10];
+ EXPECT_FALSE(absl::is_trivially_move_assignable<int10>::value);
+
+ // Verify that references are handled correctly
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&&>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&>::value);
+}
+
TEST(TypeTraitsTest, TestTrivialCopyAssign) {
// Verify that arithmetic types and pointers have trivial copy
// assignment operators.
@@ -577,7 +796,8 @@ TEST(TypeTraitsTest, TestTrivialCopyAssign) {
// Verify that types without them (i.e. nontrivial or deleted) are not.
EXPECT_FALSE(absl::is_trivially_copy_assignable<NontrivialCopyAssign>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<DeletedCopyAssign>::value);
- EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyable>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<MovableNonCopyable>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyableOrMovable>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_copy_assignable<Base>::value);
@@ -611,6 +831,116 @@ TEST(TypeTraitsTest, TestTrivialCopyAssign) {
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value);
}
+TEST(TypeTraitsTest, TestTriviallyCopyable) {
+ // Verify that arithmetic types and pointers are trivially copyable.
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<bool>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<char>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<unsigned char>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<signed char>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<wchar_t>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<unsigned int>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<int16_t>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<uint16_t>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<int64_t>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<uint64_t>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<float>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<double>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<long double>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<std::string*>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial*>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
+ const std::string*>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<const Trivial*>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<std::string**>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial**>::value);
+
+ // const qualified types are not assignable but are constructible
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<const int>::value);
+
+ // Trivial copy constructor/assignment and destructor.
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial>::value);
+ // Trivial copy assignment, but non-trivial copy constructor/destructor.
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ TrivialCopyAssign>::value);
+ // Trivial copy constructor, but non-trivial assignment.
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ TrivialCopyCtor>::value);
+
+ // Types with a non-trivial copy constructor/assignment
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ NontrivialCopyCtor>::value);
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ NontrivialCopyAssign>::value);
+
+ // Types without copy constructor/assignment, but with move
+ // MSVC disagrees with other compilers about this:
+ // EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
+ // MovableNonCopyable>::value);
+
+ // Types without copy/move constructor/assignment
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ NonCopyableOrMovable>::value);
+
+ // No copy assign, but has trivial copy constructor.
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
+ DeletedCopyAssign>::value);
+
+ // types with vtables
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<Base>::value);
+
+ // Verify that simple_pair is trivially copyable if members are
+ EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, char*>>::value));
+ EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, Trivial>>::value));
+
+ // Verify that types not trivially copyable are
+ // correctly marked as such.
+ EXPECT_FALSE(
+ absl::type_traits_internal::is_trivially_copyable<std::string>::value);
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ std::vector<int>>::value);
+
+ // Verify that simple_pairs of types not trivially copyable
+ // are not marked as trivial.
+ EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, std::string>>::value));
+ EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<std::string, int>>::value));
+ EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, TrivialCopyAssign>>::value));
+
+ // Verify that arrays of trivially copyable types are trivially copyable
+ using int10 = int[10];
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int10>::value);
+ using int10x10 = int[10][10];
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<int10x10>::value);
+
+ // Verify that references are handled correctly
+ EXPECT_FALSE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial&&>::value);
+ EXPECT_FALSE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial&>::value);
+}
+
#define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...) \
EXPECT_TRUE((std::is_same<typename std::trait_name<__VA_ARGS__>::type, \
absl::trait_name##_t<__VA_ARGS__>>::value))
@@ -953,4 +1283,85 @@ TEST(TypeTraitsTest, IsMoveAssignable) {
#endif // _LIBCPP_VERSION
}
+namespace adl_namespace {
+
+struct DeletedSwap {
+};
+
+void swap(DeletedSwap&, DeletedSwap&) = delete;
+
+struct SpecialNoexceptSwap {
+ SpecialNoexceptSwap(SpecialNoexceptSwap&&) {}
+ SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; }
+ ~SpecialNoexceptSwap() = default;
+};
+
+void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {}
+
+} // namespace adl_namespace
+
+TEST(TypeTraitsTest, IsSwappable) {
+ using absl::type_traits_internal::IsSwappable;
+ using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+ EXPECT_TRUE(IsSwappable<int>::value);
+
+ struct S {};
+ EXPECT_TRUE(IsSwappable<S>::value);
+
+ struct NoConstruct {
+ NoConstruct(NoConstruct&&) = delete;
+ NoConstruct& operator=(NoConstruct&&) { return *this; }
+ ~NoConstruct() = default;
+ };
+
+ EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value);
+ struct NoAssign {
+ NoAssign(NoAssign&&) {}
+ NoAssign& operator=(NoAssign&&) = delete;
+ ~NoAssign() = default;
+ };
+
+ EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value);
+
+ EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value);
+
+ EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
+TEST(TypeTraitsTest, IsNothrowSwappable) {
+ using absl::type_traits_internal::IsNothrowSwappable;
+ using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+ EXPECT_TRUE(IsNothrowSwappable<int>::value);
+
+ struct NonNoexceptMoves {
+ NonNoexceptMoves(NonNoexceptMoves&&) {}
+ NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; }
+ ~NonNoexceptMoves() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value);
+
+ struct NoConstruct {
+ NoConstruct(NoConstruct&&) = delete;
+ NoConstruct& operator=(NoConstruct&&) { return *this; }
+ ~NoConstruct() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value);
+
+ struct NoAssign {
+ NoAssign(NoAssign&&) {}
+ NoAssign& operator=(NoAssign&&) = delete;
+ ~NoAssign() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value);
+
+ EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value);
+
+ EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
} // namespace