diff options
author | Abseil Team <absl-team@google.com> | 2018-08-07T18·43-0700 |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2018-08-08T13·53-0400 |
commit | 083d04dd4a62ebbf037079b06e49b323c5e1192a (patch) | |
tree | c403907fc531e9061cab3007b1cc0d29aa56969c /absl/meta | |
parent | bea85b52733022294eef108a2e42d77b616ddca2 (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.h | 23 | ||||
-rw-r--r-- | absl/meta/type_traits_test.cc | 76 |
2 files changed, 96 insertions, 3 deletions
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 457b890841a6..23ebd6ed0990 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 81b4bd323977..f51f5dedee43 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 |