diff options
author | 2023-01-20 15:12:54 -0800 | |
---|---|---|
committer | 2023-01-20 15:13:57 -0800 | |
commit | 4eef16170014f75f4291ae335a271900f89eaedf (patch) | |
tree | 6fc9afd5117a11d1d0c1f2e6bbd44f554d3f3187 /absl | |
parent | 52495da05f5d3b38c9127ae842cd5ef34ec90525 (diff) |
Update absl::allocator_traits and absl::pointer_traits to always
use std::allocator_traits and std::pointer traits.
Note that the reason given in the comments for these implementations was
incorrect. Both of these exist in C++11, but not all compilers had
working implementations, so Abseil backfiled them. All supported compilers
now have working implementations.
https://en.cppreference.com/w/cpp/memory/allocator_traits
https://en.cppreference.com/w/cpp/memory/pointer_traits
Documentation has been updated to recommend the std:: spellings.
Fixes #1366
PiperOrigin-RevId: 503532746
Change-Id: Ia437f65a4c752581195dc582a41831b479d096c6
Diffstat (limited to 'absl')
-rw-r--r-- | absl/memory/memory.h | 371 | ||||
-rw-r--r-- | absl/memory/memory_test.cc | 332 |
2 files changed, 20 insertions, 683 deletions
diff --git a/absl/memory/memory.h b/absl/memory/memory.h index e5ff0e65..3508135c 100644 --- a/absl/memory/memory.h +++ b/absl/memory/memory.h @@ -158,6 +158,26 @@ std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) { return std::weak_ptr<T>(ptr); } +// ----------------------------------------------------------------------------- +// Class Template: pointer_traits +// ----------------------------------------------------------------------------- +// +// Historical note: Abseil once provided an implementation of +// `std::pointer_traits` for platforms that had not yet provided it. Those +// platforms are no longer supported. New code should simply use +// `std::pointer_traits`. +using std::pointer_traits; + +// ----------------------------------------------------------------------------- +// Class Template: allocator_traits +// ----------------------------------------------------------------------------- +// +// Historical note: Abseil once provided an implementation of +// `std::allocator_traits` for platforms that had not yet provided it. Those +// platforms are no longer supported. New code should simply use +// `std::allocator_traits`. +using std::allocator_traits; + namespace memory_internal { // ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D. @@ -175,357 +195,6 @@ struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> { template <template <typename> class Extract, typename Obj, typename Default> using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type; -// Extractors for the features of allocators. -template <typename T> -using GetPointer = typename T::pointer; - -template <typename T> -using GetConstPointer = typename T::const_pointer; - -template <typename T> -using GetVoidPointer = typename T::void_pointer; - -template <typename T> -using GetConstVoidPointer = typename T::const_void_pointer; - -template <typename T> -using GetDifferenceType = typename T::difference_type; - -template <typename T> -using GetSizeType = typename T::size_type; - -template <typename T> -using GetPropagateOnContainerCopyAssignment = - typename T::propagate_on_container_copy_assignment; - -template <typename T> -using GetPropagateOnContainerMoveAssignment = - typename T::propagate_on_container_move_assignment; - -template <typename T> -using GetPropagateOnContainerSwap = typename T::propagate_on_container_swap; - -template <typename T> -using GetIsAlwaysEqual = typename T::is_always_equal; - -template <typename T> -struct GetFirstArg; - -template <template <typename...> class Class, typename T, typename... Args> -struct GetFirstArg<Class<T, Args...>> { - using type = T; -}; - -template <typename Ptr, typename = void> -struct ElementType { - using type = typename GetFirstArg<Ptr>::type; -}; - -template <typename T> -struct ElementType<T, void_t<typename T::element_type>> { - using type = typename T::element_type; -}; - -template <typename T, typename U> -struct RebindFirstArg; - -template <template <typename...> class Class, typename T, typename... Args, - typename U> -struct RebindFirstArg<Class<T, Args...>, U> { - using type = Class<U, Args...>; -}; - -template <typename T, typename U, typename = void> -struct RebindPtr { - using type = typename RebindFirstArg<T, U>::type; -}; - -template <typename T, typename U> -struct RebindPtr<T, U, void_t<typename T::template rebind<U>>> { - using type = typename T::template rebind<U>; -}; - -template <typename T, typename U> -constexpr bool HasRebindAlloc(...) { - return false; -} - -template <typename T, typename U> -constexpr bool HasRebindAlloc(typename T::template rebind<U>::other*) { - return true; -} - -template <typename T, typename U, bool = HasRebindAlloc<T, U>(nullptr)> -struct RebindAlloc { - using type = typename RebindFirstArg<T, U>::type; -}; - -template <typename T, typename U> -struct RebindAlloc<T, U, true> { - using type = typename T::template rebind<U>::other; -}; - -} // namespace memory_internal - -// ----------------------------------------------------------------------------- -// Class Template: pointer_traits -// ----------------------------------------------------------------------------- -// -// An implementation of C++11's std::pointer_traits. -// -// Provided for portability on toolchains that have a working C++11 compiler, -// but the standard library is lacking in C++11 support. For example, some -// version of the Android NDK. -// - -template <typename Ptr> -struct pointer_traits { - using pointer = Ptr; - - // element_type: - // Ptr::element_type if present. Otherwise T if Ptr is a template - // instantiation Template<T, Args...> - using element_type = typename memory_internal::ElementType<Ptr>::type; - - // difference_type: - // Ptr::difference_type if present, otherwise std::ptrdiff_t - using difference_type = - memory_internal::ExtractOrT<memory_internal::GetDifferenceType, Ptr, - std::ptrdiff_t>; - - // rebind: - // Ptr::rebind<U> if exists, otherwise Template<U, Args...> if Ptr is a - // template instantiation Template<T, Args...> - template <typename U> - using rebind = typename memory_internal::RebindPtr<Ptr, U>::type; - - // pointer_to: - // Calls Ptr::pointer_to(r) - static pointer pointer_to(element_type& r) { // NOLINT(runtime/references) - return Ptr::pointer_to(r); - } -}; - -// Specialization for T*. -template <typename T> -struct pointer_traits<T*> { - using pointer = T*; - using element_type = T; - using difference_type = std::ptrdiff_t; - - template <typename U> - using rebind = U*; - - // pointer_to: - // Calls std::addressof(r) - static pointer pointer_to( - element_type& r) noexcept { // NOLINT(runtime/references) - return std::addressof(r); - } -}; - -// ----------------------------------------------------------------------------- -// Class Template: allocator_traits -// ----------------------------------------------------------------------------- -// -// A C++11 compatible implementation of C++17's std::allocator_traits. -// -#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -using std::allocator_traits; -#else // __cplusplus >= 201703L -template <typename Alloc> -struct allocator_traits { - using allocator_type = Alloc; - - // value_type: - // Alloc::value_type - using value_type = typename Alloc::value_type; - - // pointer: - // Alloc::pointer if present, otherwise value_type* - using pointer = memory_internal::ExtractOrT<memory_internal::GetPointer, - Alloc, value_type*>; - - // const_pointer: - // Alloc::const_pointer if present, otherwise - // absl::pointer_traits<pointer>::rebind<const value_type> - using const_pointer = - memory_internal::ExtractOrT<memory_internal::GetConstPointer, Alloc, - typename absl::pointer_traits<pointer>:: - template rebind<const value_type>>; - - // void_pointer: - // Alloc::void_pointer if present, otherwise - // absl::pointer_traits<pointer>::rebind<void> - using void_pointer = memory_internal::ExtractOrT< - memory_internal::GetVoidPointer, Alloc, - typename absl::pointer_traits<pointer>::template rebind<void>>; - - // const_void_pointer: - // Alloc::const_void_pointer if present, otherwise - // absl::pointer_traits<pointer>::rebind<const void> - using const_void_pointer = memory_internal::ExtractOrT< - memory_internal::GetConstVoidPointer, Alloc, - typename absl::pointer_traits<pointer>::template rebind<const void>>; - - // difference_type: - // Alloc::difference_type if present, otherwise - // absl::pointer_traits<pointer>::difference_type - using difference_type = memory_internal::ExtractOrT< - memory_internal::GetDifferenceType, Alloc, - typename absl::pointer_traits<pointer>::difference_type>; - - // size_type: - // Alloc::size_type if present, otherwise - // std::make_unsigned<difference_type>::type - using size_type = memory_internal::ExtractOrT< - memory_internal::GetSizeType, Alloc, - typename std::make_unsigned<difference_type>::type>; - - // propagate_on_container_copy_assignment: - // Alloc::propagate_on_container_copy_assignment if present, otherwise - // std::false_type - using propagate_on_container_copy_assignment = memory_internal::ExtractOrT< - memory_internal::GetPropagateOnContainerCopyAssignment, Alloc, - std::false_type>; - - // propagate_on_container_move_assignment: - // Alloc::propagate_on_container_move_assignment if present, otherwise - // std::false_type - using propagate_on_container_move_assignment = memory_internal::ExtractOrT< - memory_internal::GetPropagateOnContainerMoveAssignment, Alloc, - std::false_type>; - - // propagate_on_container_swap: - // Alloc::propagate_on_container_swap if present, otherwise std::false_type - using propagate_on_container_swap = - memory_internal::ExtractOrT<memory_internal::GetPropagateOnContainerSwap, - Alloc, std::false_type>; - - // is_always_equal: - // Alloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type - using is_always_equal = - memory_internal::ExtractOrT<memory_internal::GetIsAlwaysEqual, Alloc, - typename std::is_empty<Alloc>::type>; - - // rebind_alloc: - // Alloc::rebind<T>::other if present, otherwise Alloc<T, Args> if this Alloc - // is Alloc<U, Args> - template <typename T> - using rebind_alloc = typename memory_internal::RebindAlloc<Alloc, T>::type; - - // rebind_traits: - // absl::allocator_traits<rebind_alloc<T>> - template <typename T> - using rebind_traits = absl::allocator_traits<rebind_alloc<T>>; - - // allocate(Alloc& a, size_type n): - // Calls a.allocate(n) - static pointer allocate(Alloc& a, // NOLINT(runtime/references) - size_type n) { - return a.allocate(n); - } - - // allocate(Alloc& a, size_type n, const_void_pointer hint): - // Calls a.allocate(n, hint) if possible. - // If not possible, calls a.allocate(n) - static pointer allocate(Alloc& a, size_type n, // NOLINT(runtime/references) - const_void_pointer hint) { - return allocate_impl(0, a, n, hint); - } - - // deallocate(Alloc& a, pointer p, size_type n): - // Calls a.deallocate(p, n) - static void deallocate(Alloc& a, pointer p, // NOLINT(runtime/references) - size_type n) { - a.deallocate(p, n); - } - - // construct(Alloc& a, T* p, Args&&... args): - // Calls a.construct(p, std::forward<Args>(args)...) if possible. - // If not possible, calls - // ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...) - template <typename T, typename... Args> - static void construct(Alloc& a, T* p, // NOLINT(runtime/references) - Args&&... args) { - construct_impl(0, a, p, std::forward<Args>(args)...); - } - - // destroy(Alloc& a, T* p): - // Calls a.destroy(p) if possible. If not possible, calls p->~T(). - template <typename T> - static void destroy(Alloc& a, T* p) { // NOLINT(runtime/references) - destroy_impl(0, a, p); - } - - // max_size(const Alloc& a): - // Returns a.max_size() if possible. If not possible, returns - // std::numeric_limits<size_type>::max() / sizeof(value_type) - static size_type max_size(const Alloc& a) { return max_size_impl(0, a); } - - // select_on_container_copy_construction(const Alloc& a): - // Returns a.select_on_container_copy_construction() if possible. - // If not possible, returns a. - static Alloc select_on_container_copy_construction(const Alloc& a) { - return select_on_container_copy_construction_impl(0, a); - } - - private: - template <typename A> - static auto allocate_impl(int, A& a, // NOLINT(runtime/references) - size_type n, const_void_pointer hint) - -> decltype(a.allocate(n, hint)) { - return a.allocate(n, hint); - } - static pointer allocate_impl(char, Alloc& a, // NOLINT(runtime/references) - size_type n, const_void_pointer) { - return a.allocate(n); - } - - template <typename A, typename... Args> - static auto construct_impl(int, A& a, // NOLINT(runtime/references) - Args&&... args) - -> decltype(a.construct(std::forward<Args>(args)...)) { - a.construct(std::forward<Args>(args)...); - } - - template <typename T, typename... Args> - static void construct_impl(char, Alloc&, T* p, Args&&... args) { - ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); - } - - template <typename A, typename T> - static auto destroy_impl(int, A& a, // NOLINT(runtime/references) - T* p) -> decltype(a.destroy(p)) { - a.destroy(p); - } - template <typename T> - static void destroy_impl(char, Alloc&, T* p) { - p->~T(); - } - - template <typename A> - static auto max_size_impl(int, const A& a) -> decltype(a.max_size()) { - return a.max_size(); - } - static size_type max_size_impl(char, const Alloc&) { - return (std::numeric_limits<size_type>::max)() / sizeof(value_type); - } - - template <typename A> - static auto select_on_container_copy_construction_impl(int, const A& a) - -> decltype(a.select_on_container_copy_construction()) { - return a.select_on_container_copy_construction(); - } - static Alloc select_on_container_copy_construction_impl(char, - const Alloc& a) { - return a; - } -}; -#endif // __cplusplus >= 201703L - -namespace memory_internal { - // This template alias transforms Alloc::is_nothrow into a metafunction with // Alloc as a parameter so it can be used with ExtractOrT<>. template <typename Alloc> diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc index 6f01cdff..fafd3a41 100644 --- a/absl/memory/memory_test.cc +++ b/absl/memory/memory_test.cc @@ -190,338 +190,6 @@ TEST(RawPtrTest, NotAPointer) { } */ -template <typename T> -struct SmartPointer { - using difference_type = char; -}; - -struct PointerWith { - using element_type = int32_t; - using difference_type = int16_t; - template <typename U> - using rebind = SmartPointer<U>; - - static PointerWith pointer_to( - element_type& r) { // NOLINT(runtime/references) - return PointerWith{&r}; - } - - element_type* ptr; -}; - -template <typename... Args> -struct PointerWithout {}; - -TEST(PointerTraits, Types) { - using TraitsWith = absl::pointer_traits<PointerWith>; - EXPECT_TRUE((std::is_same<TraitsWith::pointer, PointerWith>::value)); - EXPECT_TRUE((std::is_same<TraitsWith::element_type, int32_t>::value)); - EXPECT_TRUE((std::is_same<TraitsWith::difference_type, int16_t>::value)); - EXPECT_TRUE(( - std::is_same<TraitsWith::rebind<int64_t>, SmartPointer<int64_t>>::value)); - - using TraitsWithout = absl::pointer_traits<PointerWithout<double, int>>; - EXPECT_TRUE((std::is_same<TraitsWithout::pointer, - PointerWithout<double, int>>::value)); - EXPECT_TRUE((std::is_same<TraitsWithout::element_type, double>::value)); - EXPECT_TRUE( - (std::is_same<TraitsWithout ::difference_type, std::ptrdiff_t>::value)); - EXPECT_TRUE((std::is_same<TraitsWithout::rebind<int64_t>, - PointerWithout<int64_t, int>>::value)); - - using TraitsRawPtr = absl::pointer_traits<char*>; - EXPECT_TRUE((std::is_same<TraitsRawPtr::pointer, char*>::value)); - EXPECT_TRUE((std::is_same<TraitsRawPtr::element_type, char>::value)); - EXPECT_TRUE( - (std::is_same<TraitsRawPtr::difference_type, std::ptrdiff_t>::value)); - EXPECT_TRUE((std::is_same<TraitsRawPtr::rebind<int64_t>, int64_t*>::value)); -} - -TEST(PointerTraits, Functions) { - int i; - EXPECT_EQ(&i, absl::pointer_traits<PointerWith>::pointer_to(i).ptr); - EXPECT_EQ(&i, absl::pointer_traits<int*>::pointer_to(i)); -} - -TEST(AllocatorTraits, Typedefs) { - struct A { - struct value_type {}; - }; - EXPECT_TRUE(( - std::is_same<A, - typename absl::allocator_traits<A>::allocator_type>::value)); - EXPECT_TRUE( - (std::is_same<A::value_type, - typename absl::allocator_traits<A>::value_type>::value)); - - struct X {}; - struct HasPointer { - using value_type = X; - using pointer = SmartPointer<X>; - }; - EXPECT_TRUE((std::is_same<SmartPointer<X>, typename absl::allocator_traits< - HasPointer>::pointer>::value)); - EXPECT_TRUE( - (std::is_same<A::value_type*, - typename absl::allocator_traits<A>::pointer>::value)); - - EXPECT_TRUE( - (std::is_same< - SmartPointer<const X>, - typename absl::allocator_traits<HasPointer>::const_pointer>::value)); - EXPECT_TRUE( - (std::is_same<const A::value_type*, - typename absl::allocator_traits<A>::const_pointer>::value)); - - struct HasVoidPointer { - using value_type = X; - struct void_pointer {}; - }; - - EXPECT_TRUE((std::is_same<HasVoidPointer::void_pointer, - typename absl::allocator_traits< - HasVoidPointer>::void_pointer>::value)); - EXPECT_TRUE( - (std::is_same<SmartPointer<void>, typename absl::allocator_traits< - HasPointer>::void_pointer>::value)); - - struct HasConstVoidPointer { - using value_type = X; - struct const_void_pointer {}; - }; - - EXPECT_TRUE( - (std::is_same<HasConstVoidPointer::const_void_pointer, - typename absl::allocator_traits< - HasConstVoidPointer>::const_void_pointer>::value)); - EXPECT_TRUE((std::is_same<SmartPointer<const void>, - typename absl::allocator_traits< - HasPointer>::const_void_pointer>::value)); - - struct HasDifferenceType { - using value_type = X; - using difference_type = int; - }; - EXPECT_TRUE( - (std::is_same<int, typename absl::allocator_traits< - HasDifferenceType>::difference_type>::value)); - EXPECT_TRUE((std::is_same<char, typename absl::allocator_traits< - HasPointer>::difference_type>::value)); - - struct HasSizeType { - using value_type = X; - using size_type = unsigned int; - }; - EXPECT_TRUE((std::is_same<unsigned int, typename absl::allocator_traits< - HasSizeType>::size_type>::value)); - EXPECT_TRUE((std::is_same<unsigned char, typename absl::allocator_traits< - HasPointer>::size_type>::value)); - - struct HasPropagateOnCopy { - using value_type = X; - struct propagate_on_container_copy_assignment {}; - }; - - EXPECT_TRUE( - (std::is_same<HasPropagateOnCopy::propagate_on_container_copy_assignment, - typename absl::allocator_traits<HasPropagateOnCopy>:: - propagate_on_container_copy_assignment>::value)); - EXPECT_TRUE( - (std::is_same<std::false_type, - typename absl::allocator_traits< - A>::propagate_on_container_copy_assignment>::value)); - - struct HasPropagateOnMove { - using value_type = X; - struct propagate_on_container_move_assignment {}; - }; - - EXPECT_TRUE( - (std::is_same<HasPropagateOnMove::propagate_on_container_move_assignment, - typename absl::allocator_traits<HasPropagateOnMove>:: - propagate_on_container_move_assignment>::value)); - EXPECT_TRUE( - (std::is_same<std::false_type, - typename absl::allocator_traits< - A>::propagate_on_container_move_assignment>::value)); - - struct HasPropagateOnSwap { - using value_type = X; - struct propagate_on_container_swap {}; - }; - - EXPECT_TRUE( - (std::is_same<HasPropagateOnSwap::propagate_on_container_swap, - typename absl::allocator_traits<HasPropagateOnSwap>:: - propagate_on_container_swap>::value)); - EXPECT_TRUE( - (std::is_same<std::false_type, typename absl::allocator_traits<A>:: - propagate_on_container_swap>::value)); - - struct HasIsAlwaysEqual { - using value_type = X; - struct is_always_equal {}; - }; - - EXPECT_TRUE((std::is_same<HasIsAlwaysEqual::is_always_equal, - typename absl::allocator_traits< - HasIsAlwaysEqual>::is_always_equal>::value)); - EXPECT_TRUE((std::is_same<std::true_type, typename absl::allocator_traits< - A>::is_always_equal>::value)); - struct NonEmpty { - using value_type = X; - int i; - }; - EXPECT_TRUE( - (std::is_same<std::false_type, - absl::allocator_traits<NonEmpty>::is_always_equal>::value)); -} - -template <typename T> -struct AllocWithPrivateInheritance : private std::allocator<T> { - using value_type = T; -}; - -TEST(AllocatorTraits, RebindWithPrivateInheritance) { - // Regression test for some versions of gcc that do not like the sfinae we - // used in combination with private inheritance. - EXPECT_TRUE( - (std::is_same<AllocWithPrivateInheritance<int>, - absl::allocator_traits<AllocWithPrivateInheritance<char>>:: - rebind_alloc<int>>::value)); -} - -template <typename T> -struct Rebound {}; - -struct AllocWithRebind { - using value_type = int; - template <typename T> - struct rebind { - using other = Rebound<T>; - }; -}; - -template <typename T, typename U> -struct AllocWithoutRebind { - using value_type = int; -}; - -TEST(AllocatorTraits, Rebind) { - EXPECT_TRUE( - (std::is_same<Rebound<int>, - typename absl::allocator_traits< - AllocWithRebind>::template rebind_alloc<int>>::value)); - EXPECT_TRUE( - (std::is_same<absl::allocator_traits<Rebound<int>>, - typename absl::allocator_traits< - AllocWithRebind>::template rebind_traits<int>>::value)); - - EXPECT_TRUE( - (std::is_same<AllocWithoutRebind<double, char>, - typename absl::allocator_traits<AllocWithoutRebind< - int, char>>::template rebind_alloc<double>>::value)); - EXPECT_TRUE( - (std::is_same<absl::allocator_traits<AllocWithoutRebind<double, char>>, - typename absl::allocator_traits<AllocWithoutRebind< - int, char>>::template rebind_traits<double>>::value)); -} - -struct TestValue { - TestValue() {} - explicit TestValue(int* trace) : trace(trace) { ++*trace; } - ~TestValue() { - if (trace) --*trace; - } - int* trace = nullptr; -}; - -struct MinimalMockAllocator { - MinimalMockAllocator() : value(0) {} - explicit MinimalMockAllocator(int value) : value(value) {} - MinimalMockAllocator(const MinimalMockAllocator& other) - : value(other.value) {} - using value_type = TestValue; - MOCK_METHOD(value_type*, allocate, (size_t)); - MOCK_METHOD(void, deallocate, (value_type*, size_t)); - - int value; -}; - -TEST(AllocatorTraits, FunctionsMinimal) { - int trace = 0; - int hint; - alignas(TestValue) char buffer[sizeof(TestValue)]; - auto* x = reinterpret_cast<TestValue*>(buffer); - MinimalMockAllocator mock; - using Traits = absl::allocator_traits<MinimalMockAllocator>; - EXPECT_CALL(mock, allocate(7)).WillRepeatedly(Return(x)); - EXPECT_CALL(mock, deallocate(x, 7)); - - EXPECT_EQ(x, Traits::allocate(mock, 7)); - static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint))); - EXPECT_EQ(x, Traits::allocate(mock, 7, static_cast<const void*>(&hint))); - Traits::deallocate(mock, x, 7); - - EXPECT_EQ(0, trace); - Traits::construct(mock, x, &trace); - EXPECT_EQ(1, trace); - Traits::destroy(mock, x); - EXPECT_EQ(0, trace); - - EXPECT_EQ(std::numeric_limits<size_t>::max() / sizeof(TestValue), - Traits::max_size(mock)); - - EXPECT_EQ(0, mock.value); - EXPECT_EQ(0, Traits::select_on_container_copy_construction(mock).value); -} - -struct FullMockAllocator { - FullMockAllocator() : value(0) {} - explicit FullMockAllocator(int value) : value(value) {} - FullMockAllocator(const FullMockAllocator& other) : value(other.value) {} - using value_type = TestValue; - MOCK_METHOD(value_type*, allocate, (size_t)); - MOCK_METHOD(value_type*, allocate, (size_t, const void*)); - MOCK_METHOD(void, construct, (value_type*, int*)); - MOCK_METHOD(void, destroy, (value_type*)); - MOCK_METHOD(size_t, max_size, (), - (const)); - MOCK_METHOD(FullMockAllocator, select_on_container_copy_construction, (), - (const)); - - int value; -}; - -TEST(AllocatorTraits, FunctionsFull) { - int trace = 0; - int hint; - TestValue x(&trace), y; - FullMockAllocator mock; - using Traits = absl::allocator_traits<FullMockAllocator>; - EXPECT_CALL(mock, allocate(7)).WillRepeatedly(Return(&x)); - EXPECT_CALL(mock, allocate(13, &hint)).WillRepeatedly(Return(&y)); - EXPECT_CALL(mock, construct(&x, &trace)); - EXPECT_CALL(mock, destroy(&x)); - EXPECT_CALL(mock, max_size()).WillRepeatedly(Return(17u)); - EXPECT_CALL(mock, select_on_container_copy_construction()) - .WillRepeatedly(Return(FullMockAllocator(23))); - - EXPECT_EQ(&x, Traits::allocate(mock, 7)); - EXPECT_EQ(&y, Traits::allocate(mock, 13, static_cast<const void*>(&hint))); - - EXPECT_EQ(1, trace); - Traits::construct(mock, &x, &trace); - EXPECT_EQ(1, trace); - Traits::destroy(mock, &x); - EXPECT_EQ(1, trace); - - EXPECT_EQ(17u, Traits::max_size(mock)); - - EXPECT_EQ(0, mock.value); - EXPECT_EQ(23, Traits::select_on_container_copy_construction(mock).value); -} - TEST(AllocatorNoThrowTest, DefaultAllocator) { #if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW EXPECT_TRUE(absl::default_allocator_is_nothrow::value); |