| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_ |
| #define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_ |
|
|
| #include <cstddef> |
| #include <cstring> |
| #include <memory> |
| #include <new> |
| #include <type_traits> |
| #include <utility> |
|
|
| #include "absl/meta/type_traits.h" |
|
|
| namespace absl { |
| ABSL_NAMESPACE_BEGIN |
| namespace container_internal { |
|
|
| |
| template <class Policy, class = void> |
| struct common_policy_traits { |
| |
| using slot_type = typename Policy::slot_type; |
| using reference = decltype(Policy::element(std::declval<slot_type*>())); |
| using value_type = typename std::remove_reference<reference>::type; |
|
|
| |
| |
| template <class Alloc, class... Args> |
| static void construct(Alloc* alloc, slot_type* slot, Args&&... args) { |
| Policy::construct(alloc, slot, std::forward<Args>(args)...); |
| } |
|
|
| |
| |
| template <class Alloc> |
| static void destroy(Alloc* alloc, slot_type* slot) { |
| Policy::destroy(alloc, slot); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template <class Alloc> |
| static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) { |
| transfer_impl(alloc, new_slot, old_slot, Rank0{}); |
| } |
|
|
| |
| |
| |
| |
| template <class P = Policy> |
| static auto element(absl::remove_const_t<slot_type>* slot) |
| -> decltype(P::element(slot)) { |
| return P::element(slot); |
| } |
| template <class P = Policy> |
| static auto element(const slot_type* slot) -> decltype(P::element(slot)) { |
| return P::element(slot); |
| } |
|
|
| static constexpr bool transfer_uses_memcpy() { |
| return std::is_same<decltype(transfer_impl<std::allocator<char>>( |
| nullptr, nullptr, nullptr, Rank0{})), |
| std::true_type>::value; |
| } |
|
|
| private: |
| |
| struct Rank2 {}; |
| struct Rank1 : Rank2 {}; |
| struct Rank0 : Rank1 {}; |
|
|
| |
| |
| |
| template <class Alloc, class P = Policy> |
| static auto transfer_impl(Alloc* alloc, slot_type* new_slot, |
| slot_type* old_slot, Rank0) |
| -> decltype(P::transfer(alloc, new_slot, old_slot)) { |
| return P::transfer(alloc, new_slot, old_slot); |
| } |
| #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 |
| |
| |
| template <class Alloc, |
| typename = std::enable_if_t<absl::is_trivially_relocatable< |
| std::conditional_t<false, Alloc, value_type>>::value>> |
| static std::true_type transfer_impl(Alloc*, slot_type* new_slot, |
| slot_type* old_slot, Rank1) { |
| |
| |
| std::memcpy( |
| static_cast<void*>(std::launder( |
| const_cast<std::remove_const_t<value_type>*>(&element(new_slot)))), |
| static_cast<const void*>(&element(old_slot)), sizeof(value_type)); |
| return {}; |
| } |
| #endif |
|
|
| template <class Alloc> |
| static void transfer_impl(Alloc* alloc, slot_type* new_slot, |
| slot_type* old_slot, Rank2) { |
| construct(alloc, new_slot, std::move(element(old_slot))); |
| destroy(alloc, old_slot); |
| } |
| }; |
|
|
| } |
| ABSL_NAMESPACE_END |
| } |
|
|
| #endif |
|
|