summaryrefslogtreecommitdiff
path: root/absl/meta
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2018-08-07 11:43:34 -0700
committerGravatar Derek Mauro <dmauro@google.com>2018-08-08 09:53:34 -0400
commit083d04dd4a62ebbf037079b06e49b323c5e1192a (patch)
treec403907fc531e9061cab3007b1cc0d29aa56969c /absl/meta
parentbea85b52733022294eef108a2e42d77b616ddca2 (diff)
Export of internal Abseil changes.
-- c1f3a243ff3713917eaf0255c86ddd1b40461ba9 by Abseil Team <absl-team@google.com>: Remove stray space. PiperOrigin-RevId: 207753171 -- 4abe43b174f7fafa390d2f6eb96f31977a38fc69 by Shaindel Schwartz <shaindel@google.com>: Typo fix. PiperOrigin-RevId: 207572868 -- e7757b409256b025cadba20a84a93cb9dc4319e1 by Abseil Team <absl-team@google.com>: Adds backported is_(copy|move)_assignable<T> PiperOrigin-RevId: 207572180 GitOrigin-RevId: c1f3a243ff3713917eaf0255c86ddd1b40461ba9 Change-Id: I1202715e5092b54d5967017728044715d6eb2ec0
Diffstat (limited to 'absl/meta')
-rw-r--r--absl/meta/type_traits.h23
-rw-r--r--absl/meta/type_traits_test.cc76
2 files changed, 96 insertions, 3 deletions
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 457b8908..23ebd6ed 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -105,8 +105,25 @@ template <class To, template <class...> class Op, class... Args>
struct is_detected_convertible
: is_detected_convertible_impl<void, To, Op, Args...>::type {};
+template <typename T>
+using IsCopyAssignableImpl =
+ decltype(std::declval<T&>() = std::declval<const T&>());
+
+template <typename T>
+using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
+
} // namespace type_traits_internal
+template <typename T>
+struct is_copy_assignable : type_traits_internal::is_detected<
+ type_traits_internal::IsCopyAssignableImpl, T> {
+};
+
+template <typename T>
+struct is_move_assignable : type_traits_internal::is_detected<
+ type_traits_internal::IsMoveAssignableImpl, T> {
+};
+
// void_t()
//
// Ignores the type of any its arguments and returns `void`. In general, this
@@ -309,7 +326,7 @@ template <typename T>
struct is_trivially_copy_assignable
: std::integral_constant<
bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
- std::is_copy_assignable<T>::value> {
+ absl::is_copy_assignable<T>::value> {
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
private:
static constexpr bool compliant =
@@ -409,11 +426,11 @@ struct IsHashEnabled
: absl::conjunction<std::is_default_constructible<std::hash<Key>>,
std::is_copy_constructible<std::hash<Key>>,
std::is_destructible<std::hash<Key>>,
- std::is_copy_assignable<std::hash<Key>>,
+ absl::is_copy_assignable<std::hash<Key>>,
IsHashable<Key>> {};
+
} // namespace type_traits_internal
} // namespace absl
-
#endif // ABSL_META_TYPE_TRAITS_H_
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 81b4bd32..f51f5ded 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -877,4 +877,80 @@ TEST(TypeTraitsTest, TestResultOf) {
EXPECT_EQ(TypeEnum::D, GetTypeExt(Wrap<TypeD>()));
}
+template <typename T>
+bool TestCopyAssign() {
+ return absl::is_copy_assignable<T>::value ==
+ std::is_copy_assignable<T>::value;
+}
+
+TEST(TypeTraitsTest, IsCopyAssignable) {
+ EXPECT_TRUE(TestCopyAssign<int>());
+ EXPECT_TRUE(TestCopyAssign<int&>());
+ EXPECT_TRUE(TestCopyAssign<int&&>());
+
+ struct S {};
+ EXPECT_TRUE(TestCopyAssign<S>());
+ EXPECT_TRUE(TestCopyAssign<S&>());
+ EXPECT_TRUE(TestCopyAssign<S&&>());
+
+ class C {
+ public:
+ explicit C(C* c) : c_(c) {}
+ ~C() { delete c_; }
+
+ private:
+ C* c_;
+ };
+ EXPECT_TRUE(TestCopyAssign<C>());
+ EXPECT_TRUE(TestCopyAssign<C&>());
+ EXPECT_TRUE(TestCopyAssign<C&&>());
+
+ // Reason for ifndef: add_lvalue_reference<T> in libc++ breaks for these cases
+#ifndef _LIBCPP_VERSION
+ EXPECT_TRUE(TestCopyAssign<int()>());
+ EXPECT_TRUE(TestCopyAssign<int(int) const>());
+ EXPECT_TRUE(TestCopyAssign<int(...) volatile&>());
+ EXPECT_TRUE(TestCopyAssign<int(int, ...) const volatile&&>());
+#endif // _LIBCPP_VERSION
+}
+
+template <typename T>
+bool TestMoveAssign() {
+ return absl::is_move_assignable<T>::value ==
+ std::is_move_assignable<T>::value;
+}
+
+TEST(TypeTraitsTest, IsMoveAssignable) {
+ EXPECT_TRUE(TestMoveAssign<int>());
+ EXPECT_TRUE(TestMoveAssign<int&>());
+ EXPECT_TRUE(TestMoveAssign<int&&>());
+
+ struct S {};
+ EXPECT_TRUE(TestMoveAssign<S>());
+ EXPECT_TRUE(TestMoveAssign<S&>());
+ EXPECT_TRUE(TestMoveAssign<S&&>());
+
+ class C {
+ public:
+ explicit C(C* c) : c_(c) {}
+ ~C() { delete c_; }
+ void operator=(const C&) = delete;
+ void operator=(C&&) = delete;
+
+ private:
+ C* c_;
+ };
+ EXPECT_TRUE(TestMoveAssign<C>());
+ EXPECT_TRUE(TestMoveAssign<C&>());
+ EXPECT_TRUE(TestMoveAssign<C&&>());
+
+ // Reason for ifndef: add_lvalue_reference<T> in libc++ breaks for these cases
+#ifndef _LIBCPP_VERSION
+ EXPECT_TRUE(TestMoveAssign<int()>());
+ EXPECT_TRUE(TestMoveAssign<int(int) const>());
+ EXPECT_TRUE(TestMoveAssign<int(...) volatile&>());
+ EXPECT_TRUE(TestMoveAssign<int(int, ...) const volatile&&>());
+#endif // _LIBCPP_VERSION
+}
+
} // namespace