#ifndef ABSL_CONTAINER_NODE_HASH_MAP_H_
#define ABSL_CONTAINER_NODE_HASH_MAP_H_
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
#include "absl/algorithm/container.h"
#include "absl/base/attributes.h"
#include "absl/container/hash_container_defaults.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/node_slot_policy.h"
#include "absl/container/internal/raw_hash_map.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <class Key, class Value>
class NodeHashMapPolicy;
}
template <class Key, class Value, class Hash = DefaultHashContainerHash<Key>,
class Eq = DefaultHashContainerEq<Key>,
class Alloc = std::allocator<std::pair<const Key, Value>>>
class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map
: public absl::container_internal::raw_hash_map<
absl::container_internal::NodeHashMapPolicy<Key, Value>, Hash, Eq,
Alloc> {
using Base = typename node_hash_map::raw_hash_map;
public:
node_hash_map() {}
using Base::Base;
using Base::begin;
using Base::cbegin;
using Base::cend;
using Base::end;
using Base::capacity;
using Base::empty;
using Base::max_size;
using Base::size;
using Base::clear;
using Base::erase;
using Base::insert;
using Base::insert_or_assign;
using Base::emplace;
using Base::emplace_hint;
using Base::try_emplace;
using Base::extract;
using Base::merge;
using Base::swap;
using Base::rehash;
using Base::reserve;
using Base::at;
using Base::contains;
using Base::count;
using Base::equal_range;
using Base::find;
using Base::operator[];
using Base::bucket_count;
using Base::load_factor;
using Base::max_load_factor;
using Base::get_allocator;
using Base::hash_function;
using Base::key_eq;
};
template <typename K, typename V, typename H, typename E, typename A,
typename Predicate>
typename node_hash_map<K, V, H, E, A>::size_type erase_if(
node_hash_map<K, V, H, E, A>& c, Predicate pred) {
return container_internal::EraseIf(pred, &c);
}
namespace container_internal {
template <typename K, typename V, typename H, typename E, typename A,
typename Function>
decay_t<Function> c_for_each_fast(const node_hash_map<K, V, H, E, A>& c,
Function&& f) {
container_internal::ForEach(f, &c);
return f;
}
template <typename K, typename V, typename H, typename E, typename A,
typename Function>
decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>& c,
Function&& f) {
container_internal::ForEach(f, &c);
return f;
}
template <typename K, typename V, typename H, typename E, typename A,
typename Function>
decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>&& c,
Function&& f) {
container_internal::ForEach(f, &c);
return f;
}
}
namespace container_internal {
template <class Key, class Value>
class NodeHashMapPolicy
: public absl::container_internal::node_slot_policy<
std::pair<const Key, Value>&, NodeHashMapPolicy<Key, Value>> {
using value_type = std::pair<const Key, Value>;
public:
using key_type = Key;
using mapped_type = Value;
using init_type = std::pair< key_type, mapped_type>;
template <class Allocator, class... Args>
static value_type* new_element(Allocator* alloc, Args&&... args) {
using PairAlloc = typename absl::allocator_traits<
Allocator>::template rebind_alloc<value_type>;
PairAlloc pair_alloc(*alloc);
value_type* res =
absl::allocator_traits<PairAlloc>::allocate(pair_alloc, 1);
absl::allocator_traits<PairAlloc>::construct(pair_alloc, res,
std::forward<Args>(args)...);
return res;
}
template <class Allocator>
static void delete_element(Allocator* alloc, value_type* pair) {
using PairAlloc = typename absl::allocator_traits<
Allocator>::template rebind_alloc<value_type>;
PairAlloc pair_alloc(*alloc);
absl::allocator_traits<PairAlloc>::destroy(pair_alloc, pair);
absl::allocator_traits<PairAlloc>::deallocate(pair_alloc, pair, 1);
}
template <class F, class... Args>
static decltype(absl::container_internal::DecomposePair(
std::declval<F>(), std::declval<Args>()...))
apply(F&& f, Args&&... args) {
return absl::container_internal::DecomposePair(std::forward<F>(f),
std::forward<Args>(args)...);
}
static size_t element_space_used(const value_type*) {
return sizeof(value_type);
}
static Value& value(value_type* elem) { return elem->second; }
static const Value& value(const value_type* elem) { return elem->second; }
template <class Hash>
static constexpr HashSlotFn get_hash_slot_fn() {
return memory_internal::IsLayoutCompatible<Key, Value>::value
? &TypeErasedDerefAndApplyToSlotFn<Hash, Key>
: nullptr;
}
};
}
namespace container_algorithm_internal {
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct IsUnorderedContainer<
absl::node_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
}
ABSL_NAMESPACE_END
}
#endif