about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--absl/base/exception_safety_testing_test.cc4
-rw-r--r--absl/meta/type_traits.h23
-rw-r--r--absl/meta/type_traits_test.cc76
-rw-r--r--absl/strings/numbers.h2
-rw-r--r--absl/strings/string_view.h2
-rw-r--r--absl/types/internal/variant.h8
-rw-r--r--absl/types/optional.h4
-rw-r--r--absl/types/optional_test.cc29
-rw-r--r--absl/types/variant_test.cc10
9 files changed, 126 insertions, 32 deletions
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index 97c8d6f83189..724c0ad547ab 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -931,8 +931,8 @@ TEST(ThrowingValueTraitsTest, RelationalOperators) {
 }
 
 TEST(ThrowingAllocatorTraitsTest, Assignablility) {
-  EXPECT_TRUE(std::is_move_assignable<ThrowingAllocator<int>>::value);
-  EXPECT_TRUE(std::is_copy_assignable<ThrowingAllocator<int>>::value);
+  EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);
+  EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value);
   EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value);
   EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);
 }
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
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index cf3c597266cf..fbed273e0957 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -44,7 +44,7 @@ namespace absl {
 // Converts the given std::string into an integer value, returning `true` if
 // successful. The std::string must reflect a base-10 integer (optionally followed or
 // preceded by ASCII whitespace) whose value falls within the range of the
-// integer type,
+// integer type.
 template <typename int_type>
 ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);
 
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index a7f9199240a2..1537a3f84283 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -141,7 +141,7 @@ namespace absl {
 // All empty `string_view` objects whether null or not, are equal:
 //
 //   absl::string_view() == absl::string_view("", 0)
-//   absl::string_view(nullptr, 0) == absl:: string_view("abcdef"+6, 0)
+//   absl::string_view(nullptr, 0) == absl::string_view("abcdef"+6, 0)
 class string_view {
  public:
   using traits_type = std::char_traits<char>;
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 7708e67cb14f..28ae1a5a7e3c 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -1227,23 +1227,23 @@ using VariantCopyBase = absl::conditional_t<
 // Base that is dependent on whether or not the move-assign can be trivial.
 template <class... T>
 using VariantMoveAssignBase = absl::conditional_t<
-    absl::disjunction<absl::conjunction<std::is_move_assignable<Union<T...>>,
+    absl::disjunction<absl::conjunction<absl::is_move_assignable<Union<T...>>,
                                         std::is_move_constructible<Union<T...>>,
                                         std::is_destructible<Union<T...>>>,
                       absl::negation<absl::conjunction<
                           std::is_move_constructible<T>...,
-                          std::is_move_assignable<T>...>>>::value,
+                          absl::is_move_assignable<T>...>>>::value,
     VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
 
 // Base that is dependent on whether or not the copy-assign can be trivial.
 template <class... T>
 using VariantCopyAssignBase = absl::conditional_t<
-    absl::disjunction<absl::conjunction<std::is_copy_assignable<Union<T...>>,
+    absl::disjunction<absl::conjunction<absl::is_copy_assignable<Union<T...>>,
                                         std::is_copy_constructible<Union<T...>>,
                                         std::is_destructible<Union<T...>>>,
                       absl::negation<absl::conjunction<
                           std::is_copy_constructible<T>...,
-                          std::is_copy_assignable<T>...>>>::value,
+                          absl::is_copy_assignable<T>...>>>::value,
     VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
 
 template <class... T>
diff --git a/absl/types/optional.h b/absl/types/optional.h
index c837cddeef48..79475e3ea3b3 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -411,10 +411,10 @@ constexpr copy_traits get_ctor_copy_traits() {
 
 template <typename T>
 constexpr copy_traits get_assign_copy_traits() {
-  return std::is_copy_assignable<T>::value &&
+  return absl::is_copy_assignable<T>::value &&
                  std::is_copy_constructible<T>::value
              ? copy_traits::copyable
-             : std::is_move_assignable<T>::value &&
+             : absl::is_move_assignable<T>::value &&
                        std::is_move_constructible<T>::value
                    ? copy_traits::movable
                    : copy_traits::non_movable;
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index 179bfd66d2fe..d90db9f821b5 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -607,11 +607,12 @@ TEST(optionalTest, CopyAssignment) {
   opt2_to_empty = empty;
   EXPECT_FALSE(opt2_to_empty);
 
-  EXPECT_FALSE(std::is_copy_assignable<absl::optional<const int>>::value);
-  EXPECT_TRUE(std::is_copy_assignable<absl::optional<Copyable>>::value);
-  EXPECT_FALSE(std::is_copy_assignable<absl::optional<MoveableThrow>>::value);
-  EXPECT_FALSE(std::is_copy_assignable<absl::optional<MoveableNoThrow>>::value);
-  EXPECT_FALSE(std::is_copy_assignable<absl::optional<NonMovable>>::value);
+  EXPECT_FALSE(absl::is_copy_assignable<absl::optional<const int>>::value);
+  EXPECT_TRUE(absl::is_copy_assignable<absl::optional<Copyable>>::value);
+  EXPECT_FALSE(absl::is_copy_assignable<absl::optional<MoveableThrow>>::value);
+  EXPECT_FALSE(
+      absl::is_copy_assignable<absl::optional<MoveableNoThrow>>::value);
+  EXPECT_FALSE(absl::is_copy_assignable<absl::optional<NonMovable>>::value);
 
   EXPECT_TRUE(absl::is_trivially_copy_assignable<int>::value);
   EXPECT_TRUE(absl::is_trivially_copy_assignable<volatile int>::value);
@@ -625,9 +626,9 @@ TEST(optionalTest, CopyAssignment) {
   };
 
   EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::value);
-  EXPECT_FALSE(std::is_copy_assignable<const Trivial>::value);
-  EXPECT_FALSE(std::is_copy_assignable<volatile Trivial>::value);
-  EXPECT_TRUE(std::is_copy_assignable<NonTrivial>::value);
+  EXPECT_FALSE(absl::is_copy_assignable<const Trivial>::value);
+  EXPECT_FALSE(absl::is_copy_assignable<volatile Trivial>::value);
+  EXPECT_TRUE(absl::is_copy_assignable<NonTrivial>::value);
   EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value);
 
   // std::optional doesn't support volatile nontrivial types.
@@ -695,11 +696,11 @@ TEST(optionalTest, MoveAssignment) {
     EXPECT_EQ(1, listener.volatile_move_assign);
   }
 #endif  // ABSL_HAVE_STD_OPTIONAL
-  EXPECT_FALSE(std::is_move_assignable<absl::optional<const int>>::value);
-  EXPECT_TRUE(std::is_move_assignable<absl::optional<Copyable>>::value);
-  EXPECT_TRUE(std::is_move_assignable<absl::optional<MoveableThrow>>::value);
-  EXPECT_TRUE(std::is_move_assignable<absl::optional<MoveableNoThrow>>::value);
-  EXPECT_FALSE(std::is_move_assignable<absl::optional<NonMovable>>::value);
+  EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value);
+  EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value);
+  EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value);
+  EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableNoThrow>>::value);
+  EXPECT_FALSE(absl::is_move_assignable<absl::optional<NonMovable>>::value);
 
   EXPECT_FALSE(
       std::is_nothrow_move_assignable<absl::optional<MoveableThrow>>::value);
@@ -1619,7 +1620,7 @@ TEST(optionalTest, AssignmentConstraints) {
   EXPECT_TRUE(
       (std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value));
   EXPECT_TRUE(std::is_move_assignable<absl::optional<AnyLike>>::value);
-  EXPECT_TRUE(std::is_copy_assignable<absl::optional<AnyLike>>::value);
+  EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
 }
 
 }  // namespace
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index 262bd9446c18..bfb8bd7a0223 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -403,7 +403,7 @@ struct is_trivially_move_constructible
 
 template <class T>
 struct is_trivially_move_assignable
-    : std::is_move_assignable<SingleUnion<T>>::type {};
+    : absl::is_move_assignable<SingleUnion<T>>::type {};
 
 TEST(VariantTest, NothrowMoveConstructible) {
   // Verify that variant is nothrow move constructible iff its template
@@ -2439,14 +2439,14 @@ TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
 
 TEST(VariantTest, TestCopyAndMoveTypeTraits) {
   EXPECT_TRUE(std::is_copy_constructible<variant<std::string>>::value);
-  EXPECT_TRUE(std::is_copy_assignable<variant<std::string>>::value);
+  EXPECT_TRUE(absl::is_copy_assignable<variant<std::string>>::value);
   EXPECT_TRUE(std::is_move_constructible<variant<std::string>>::value);
-  EXPECT_TRUE(std::is_move_assignable<variant<std::string>>::value);
+  EXPECT_TRUE(absl::is_move_assignable<variant<std::string>>::value);
   EXPECT_TRUE(std::is_move_constructible<variant<std::unique_ptr<int>>>::value);
-  EXPECT_TRUE(std::is_move_assignable<variant<std::unique_ptr<int>>>::value);
+  EXPECT_TRUE(absl::is_move_assignable<variant<std::unique_ptr<int>>>::value);
   EXPECT_FALSE(
       std::is_copy_constructible<variant<std::unique_ptr<int>>>::value);
-  EXPECT_FALSE(std::is_copy_assignable<variant<std::unique_ptr<int>>>::value);
+  EXPECT_FALSE(absl::is_copy_assignable<variant<std::unique_ptr<int>>>::value);
 
   EXPECT_FALSE(
       absl::is_trivially_copy_constructible<variant<std::string>>::value);