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
pull/163/head
Abseil Team 7 years ago committed by Derek Mauro
parent bea85b5273
commit 083d04dd4a
  1. 4
      absl/base/exception_safety_testing_test.cc
  2. 23
      absl/meta/type_traits.h
  3. 76
      absl/meta/type_traits_test.cc
  4. 2
      absl/strings/numbers.h
  5. 2
      absl/strings/string_view.h
  6. 8
      absl/types/internal/variant.h
  7. 4
      absl/types/optional.h
  8. 29
      absl/types/optional_test.cc
  9. 10
      absl/types/variant_test.cc

@ -931,8 +931,8 @@ TEST(ThrowingValueTraitsTest, RelationalOperators) {
} }
TEST(ThrowingAllocatorTraitsTest, Assignablility) { TEST(ThrowingAllocatorTraitsTest, Assignablility) {
EXPECT_TRUE(std::is_move_assignable<ThrowingAllocator<int>>::value); EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);
EXPECT_TRUE(std::is_copy_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_move_assignable<ThrowingAllocator<int>>::value);
EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value); EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);
} }

@ -105,8 +105,25 @@ template <class To, template <class...> class Op, class... Args>
struct is_detected_convertible struct is_detected_convertible
: is_detected_convertible_impl<void, To, Op, Args...>::type {}; : 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 } // 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() // void_t()
// //
// Ignores the type of any its arguments and returns `void`. In general, this // 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 struct is_trivially_copy_assignable
: std::integral_constant< : std::integral_constant<
bool, __has_trivial_assign(typename std::remove_reference<T>::type) && 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 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
private: private:
static constexpr bool compliant = static constexpr bool compliant =
@ -409,11 +426,11 @@ struct IsHashEnabled
: absl::conjunction<std::is_default_constructible<std::hash<Key>>, : absl::conjunction<std::is_default_constructible<std::hash<Key>>,
std::is_copy_constructible<std::hash<Key>>, std::is_copy_constructible<std::hash<Key>>,
std::is_destructible<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>> {}; IsHashable<Key>> {};
} // namespace type_traits_internal } // namespace type_traits_internal
} // namespace absl } // namespace absl
#endif // ABSL_META_TYPE_TRAITS_H_ #endif // ABSL_META_TYPE_TRAITS_H_

@ -877,4 +877,80 @@ TEST(TypeTraitsTest, TestResultOf) {
EXPECT_EQ(TypeEnum::D, GetTypeExt(Wrap<TypeD>())); 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 } // namespace

@ -44,7 +44,7 @@ namespace absl {
// Converts the given std::string into an integer value, returning `true` if // 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 // 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 // preceded by ASCII whitespace) whose value falls within the range of the
// integer type, // integer type.
template <typename int_type> template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out); ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);

@ -141,7 +141,7 @@ namespace absl {
// All empty `string_view` objects whether null or not, are equal: // All empty `string_view` objects whether null or not, are equal:
// //
// absl::string_view() == absl::string_view("", 0) // 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 { class string_view {
public: public:
using traits_type = std::char_traits<char>; using traits_type = std::char_traits<char>;

@ -1227,23 +1227,23 @@ using VariantCopyBase = absl::conditional_t<
// Base that is dependent on whether or not the move-assign can be trivial. // Base that is dependent on whether or not the move-assign can be trivial.
template <class... T> template <class... T>
using VariantMoveAssignBase = absl::conditional_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_move_constructible<Union<T...>>,
std::is_destructible<Union<T...>>>, std::is_destructible<Union<T...>>>,
absl::negation<absl::conjunction< absl::negation<absl::conjunction<
std::is_move_constructible<T>..., std::is_move_constructible<T>...,
std::is_move_assignable<T>...>>>::value, absl::is_move_assignable<T>...>>>::value,
VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>; VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
// Base that is dependent on whether or not the copy-assign can be trivial. // Base that is dependent on whether or not the copy-assign can be trivial.
template <class... T> template <class... T>
using VariantCopyAssignBase = absl::conditional_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_copy_constructible<Union<T...>>,
std::is_destructible<Union<T...>>>, std::is_destructible<Union<T...>>>,
absl::negation<absl::conjunction< absl::negation<absl::conjunction<
std::is_copy_constructible<T>..., std::is_copy_constructible<T>...,
std::is_copy_assignable<T>...>>>::value, absl::is_copy_assignable<T>...>>>::value,
VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>; VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
template <class... T> template <class... T>

@ -411,10 +411,10 @@ constexpr copy_traits get_ctor_copy_traits() {
template <typename T> template <typename T>
constexpr copy_traits get_assign_copy_traits() { 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 std::is_copy_constructible<T>::value
? copy_traits::copyable ? copy_traits::copyable
: std::is_move_assignable<T>::value && : absl::is_move_assignable<T>::value &&
std::is_move_constructible<T>::value std::is_move_constructible<T>::value
? copy_traits::movable ? copy_traits::movable
: copy_traits::non_movable; : copy_traits::non_movable;

@ -607,11 +607,12 @@ TEST(optionalTest, CopyAssignment) {
opt2_to_empty = empty; opt2_to_empty = empty;
EXPECT_FALSE(opt2_to_empty); EXPECT_FALSE(opt2_to_empty);
EXPECT_FALSE(std::is_copy_assignable<absl::optional<const int>>::value); EXPECT_FALSE(absl::is_copy_assignable<absl::optional<const int>>::value);
EXPECT_TRUE(std::is_copy_assignable<absl::optional<Copyable>>::value); EXPECT_TRUE(absl::is_copy_assignable<absl::optional<Copyable>>::value);
EXPECT_FALSE(std::is_copy_assignable<absl::optional<MoveableThrow>>::value); EXPECT_FALSE(absl::is_copy_assignable<absl::optional<MoveableThrow>>::value);
EXPECT_FALSE(std::is_copy_assignable<absl::optional<MoveableNoThrow>>::value); EXPECT_FALSE(
EXPECT_FALSE(std::is_copy_assignable<absl::optional<NonMovable>>::value); 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<int>::value);
EXPECT_TRUE(absl::is_trivially_copy_assignable<volatile 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_TRUE(absl::is_trivially_copy_assignable<Trivial>::value);
EXPECT_FALSE(std::is_copy_assignable<const Trivial>::value); EXPECT_FALSE(absl::is_copy_assignable<const Trivial>::value);
EXPECT_FALSE(std::is_copy_assignable<volatile Trivial>::value); EXPECT_FALSE(absl::is_copy_assignable<volatile Trivial>::value);
EXPECT_TRUE(std::is_copy_assignable<NonTrivial>::value); EXPECT_TRUE(absl::is_copy_assignable<NonTrivial>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value); EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value);
// std::optional doesn't support volatile nontrivial types. // std::optional doesn't support volatile nontrivial types.
@ -695,11 +696,11 @@ TEST(optionalTest, MoveAssignment) {
EXPECT_EQ(1, listener.volatile_move_assign); EXPECT_EQ(1, listener.volatile_move_assign);
} }
#endif // ABSL_HAVE_STD_OPTIONAL #endif // ABSL_HAVE_STD_OPTIONAL
EXPECT_FALSE(std::is_move_assignable<absl::optional<const int>>::value); EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value);
EXPECT_TRUE(std::is_move_assignable<absl::optional<Copyable>>::value); EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value);
EXPECT_TRUE(std::is_move_assignable<absl::optional<MoveableThrow>>::value); EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value);
EXPECT_TRUE(std::is_move_assignable<absl::optional<MoveableNoThrow>>::value); EXPECT_TRUE(absl::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<NonMovable>>::value);
EXPECT_FALSE( EXPECT_FALSE(
std::is_nothrow_move_assignable<absl::optional<MoveableThrow>>::value); std::is_nothrow_move_assignable<absl::optional<MoveableThrow>>::value);
@ -1619,7 +1620,7 @@ TEST(optionalTest, AssignmentConstraints) {
EXPECT_TRUE( EXPECT_TRUE(
(std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value)); (std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value));
EXPECT_TRUE(std::is_move_assignable<absl::optional<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 } // namespace

@ -403,7 +403,7 @@ struct is_trivially_move_constructible
template <class T> template <class T>
struct is_trivially_move_assignable struct is_trivially_move_assignable
: std::is_move_assignable<SingleUnion<T>>::type {}; : absl::is_move_assignable<SingleUnion<T>>::type {};
TEST(VariantTest, NothrowMoveConstructible) { TEST(VariantTest, NothrowMoveConstructible) {
// Verify that variant is nothrow move constructible iff its template // Verify that variant is nothrow move constructible iff its template
@ -2439,14 +2439,14 @@ TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
TEST(VariantTest, TestCopyAndMoveTypeTraits) { TEST(VariantTest, TestCopyAndMoveTypeTraits) {
EXPECT_TRUE(std::is_copy_constructible<variant<std::string>>::value); 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_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_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( EXPECT_FALSE(
std::is_copy_constructible<variant<std::unique_ptr<int>>>::value); 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( EXPECT_FALSE(
absl::is_trivially_copy_constructible<variant<std::string>>::value); absl::is_trivially_copy_constructible<variant<std::string>>::value);

Loading…
Cancel
Save