Remove value_type from SetNode.

This commit is contained in:
levlam 2022-02-21 02:22:01 +03:00
parent 9e8b2489bd
commit f0a2ccd0fb
4 changed files with 50 additions and 56 deletions

View File

@ -125,17 +125,16 @@ class FlatHashTableChunks {
using NodeIterator = typename fixed_vector<Node>::iterator; using NodeIterator = typename fixed_vector<Node>::iterator;
using ConstNodeIterator = typename fixed_vector<Node>::const_iterator; using ConstNodeIterator = typename fixed_vector<Node>::const_iterator;
using KeyT = typename Node::key_type; using KeyT = typename Node::public_key_type;
using key_type = typename Node::key_type; using key_type = typename Node::public_key_type;
using public_type = typename Node::public_type;
using value_type = typename Node::public_type; using value_type = typename Node::public_type;
struct Iterator { struct Iterator {
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = public_type; using value_type = FlatHashTableChunks::value_type;
using pointer = public_type *; using pointer = value_type *;
using reference = public_type &; using reference = value_type &;
friend class FlatHashTableChunks; friend class FlatHashTableChunks;
Iterator &operator++() { Iterator &operator++() {
@ -177,7 +176,7 @@ class FlatHashTableChunks {
struct ConstIterator { struct ConstIterator {
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = public_type; using value_type = FlatHashTableChunks::value_type;
using pointer = const value_type *; using pointer = const value_type *;
using reference = const value_type &; using reference = const value_type &;
@ -214,21 +213,25 @@ class FlatHashTableChunks {
using const_iterator = ConstIterator; using const_iterator = ConstIterator;
FlatHashTableChunks() = default; FlatHashTableChunks() = default;
FlatHashTableChunks(const FlatHashTableChunks &other) : FlatHashTableChunks(other.begin(), other.end()) { FlatHashTableChunks(const FlatHashTableChunks &other) {
assign(other);
} }
FlatHashTableChunks &operator=(const FlatHashTableChunks &other) { FlatHashTableChunks &operator=(const FlatHashTableChunks &other) {
assign(other.begin(), other.end()); clear();
assign(other);
return *this; return *this;
} }
FlatHashTableChunks(std::initializer_list<Node> nodes) { FlatHashTableChunks(std::initializer_list<Node> nodes) {
reserve(nodes.size()); reserve(nodes.size());
for (auto &node : nodes) { for (auto &new_node : nodes) {
CHECK(!node.empty()); CHECK(!new_node.empty());
if (count(node.key()) > 0) { if (count(new_node.key()) > 0) {
continue; continue;
} }
emplace_node(Node{node.first, node.second}); Node node;
node.copy_from(new_node);
emplace_node(std::move(node));
} }
} }
@ -247,11 +250,6 @@ class FlatHashTableChunks {
} }
~FlatHashTableChunks() = default; ~FlatHashTableChunks() = default;
template <class ItT>
FlatHashTableChunks(ItT begin, ItT end) {
assign(begin, end);
}
size_t bucket_count() const { size_t bucket_count() const {
return nodes_.size(); return nodes_.size();
} }
@ -270,7 +268,7 @@ class FlatHashTableChunks {
auto mask_it = MaskHelper::equal_mask(chunk.ctrl, hash.small_hash); auto mask_it = MaskHelper::equal_mask(chunk.ctrl, hash.small_hash);
for (auto pos : mask_it) { for (auto pos : mask_it) {
auto it = chunk_begin + pos; auto it = chunk_begin + pos;
if (likely(EqT()(it->first, key))) { if (likely(EqT()(it->key(), key))) {
return Iterator{it, this}; return Iterator{it, this};
} }
} }
@ -367,8 +365,9 @@ class FlatHashTableChunks {
} }
} }
typename Node::value_type &operator[](const KeyT &key) { template <class T = typename Node::second_type>
return emplace(key).first->value(); T &operator[](const KeyT &key) {
return emplace(key).first->second;
} }
size_t erase(const KeyT &key) { size_t erase(const KeyT &key) {
@ -419,12 +418,12 @@ class FlatHashTableChunks {
fixed_vector<Chunk> chunks_; fixed_vector<Chunk> chunks_;
size_t used_nodes_{}; size_t used_nodes_{};
template <class ItT> void assign(const FlatHashTableChunks &other) {
void assign(ItT begin, ItT end) { reserve(other.size());
clear(); for (const auto &new_node : other) {
reserve(std::distance(begin, end)); Node node;
for (; begin != end; ++begin) { node.copy_from(new_node);
emplace(begin->first, begin->second); emplace_node(std::move(node));
} }
} }
@ -508,7 +507,7 @@ class FlatHashTableChunks {
void emplace_node(Node &&node) { void emplace_node(Node &&node) {
DCHECK(!node.empty()); DCHECK(!node.empty());
auto hash = calc_hash(node.first); auto hash = calc_hash(node.key());
auto chunk_it = get_chunk_it(hash.chunk_i); auto chunk_it = get_chunk_it(hash.chunk_i);
while (true) { while (true) {
auto chunk_i = chunk_it.pos(); auto chunk_i = chunk_it.pos();
@ -543,7 +542,7 @@ class FlatHashTableChunks {
size_t empty_i = it - nodes_.begin(); size_t empty_i = it - nodes_.begin();
DCHECK(0 <= empty_i && empty_i < nodes_.size()); DCHECK(0 <= empty_i && empty_i < nodes_.size());
auto empty_chunk_i = empty_i / Chunk::CHUNK_SIZE; auto empty_chunk_i = empty_i / Chunk::CHUNK_SIZE;
auto hash = calc_hash(it->first); auto hash = calc_hash(it->key());
auto chunk_it = get_chunk_it(hash.chunk_i); auto chunk_it = get_chunk_it(hash.chunk_i);
while (true) { while (true) {
auto chunk_i = chunk_it.pos(); auto chunk_i = chunk_it.pos();

View File

@ -28,20 +28,19 @@ template <class KeyT, class ValueT>
struct MapNode { struct MapNode {
using first_type = KeyT; using first_type = KeyT;
using second_type = ValueT; using second_type = ValueT;
using key_type = KeyT; using public_key_type = KeyT;
using public_type = MapNode<KeyT, ValueT>; using public_type = MapNode;
using value_type = ValueT;
KeyT first{}; KeyT first{};
union { union {
ValueT second; ValueT second;
}; };
const auto &key() const {
const KeyT &key() const {
return first; return first;
} }
auto &value() {
return second; MapNode &get_public() {
}
auto &get_public() {
return *this; return *this;
} }
@ -100,23 +99,19 @@ struct MapNode {
template <class KeyT> template <class KeyT>
struct SetNode { struct SetNode {
using first_type = KeyT; using public_key_type = KeyT;
using key_type = KeyT;
using public_type = KeyT; using public_type = KeyT;
using value_type = KeyT;
KeyT first{}; KeyT first{};
const auto &key() const { const KeyT &key() const {
return first;
}
const auto &value() const {
return first; return first;
} }
auto &get_public() { KeyT &get_public() {
return first; return first;
} }
SetNode() = default; SetNode() = default;
explicit SetNode(KeyT key) : first(std::move(key)) { explicit SetNode(KeyT key) : first(std::move(key)) {
} }
@ -162,17 +157,16 @@ class FlatHashTable {
using NodeIterator = typename fixed_vector<Node>::iterator; using NodeIterator = typename fixed_vector<Node>::iterator;
using ConstNodeIterator = typename fixed_vector<Node>::const_iterator; using ConstNodeIterator = typename fixed_vector<Node>::const_iterator;
using KeyT = typename Node::key_type; using KeyT = typename Node::public_key_type;
using key_type = typename Node::key_type; using key_type = typename Node::public_key_type;
using public_type = typename Node::public_type;
using value_type = typename Node::public_type; using value_type = typename Node::public_type;
struct Iterator { struct Iterator {
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = public_type; using value_type = FlatHashTable::value_type;
using pointer = public_type *; using pointer = value_type *;
using reference = public_type &; using reference = value_type &;
friend class FlatHashTable; friend class FlatHashTable;
Iterator &operator++() { Iterator &operator++() {
@ -214,7 +208,7 @@ class FlatHashTable {
struct ConstIterator { struct ConstIterator {
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = public_type; using value_type = FlatHashTable::value_type;
using pointer = const value_type *; using pointer = const value_type *;
using reference = const value_type &; using reference = const value_type &;
@ -391,8 +385,9 @@ class FlatHashTable {
} }
} }
typename Node::value_type &operator[](const KeyT &key) { template <class T = typename Node::second_type>
return emplace(key).first->value(); T &operator[](const KeyT &key) {
return emplace(key).first->second;
} }
size_t erase(const KeyT &key) { size_t erase(const KeyT &key) {

View File

@ -176,7 +176,6 @@ TEST(FlatHashMap, basic) {
ASSERT_EQ("a", kv.find("a")->first); ASSERT_EQ("a", kv.find("a")->first);
ASSERT_EQ("b", kv.find("a")->second); ASSERT_EQ("b", kv.find("a")->second);
ASSERT_EQ("a", kv.find("a")->key()); ASSERT_EQ("a", kv.find("a")->key());
ASSERT_EQ("b", kv.find("a")->value());
kv.find("a")->second = "c"; kv.find("a")->second = "c";
ASSERT_EQ("c", kv.find("a")->second); ASSERT_EQ("c", kv.find("a")->second);
ASSERT_EQ("c", kv["a"]); ASSERT_EQ("c", kv["a"]);

View File

@ -190,13 +190,14 @@ static void BM_Get(benchmark::State &state) {
td::vector<KeyValue> data; td::vector<KeyValue> data;
td::vector<Key> keys; td::vector<Key> keys;
TableT table;
for (std::size_t i = 0; i < n; i++) { for (std::size_t i = 0; i < n; i++) {
auto key = rnd(); auto key = rnd();
auto value = rnd(); auto value = rnd();
data.emplace_back(key, value); data.emplace_back(key, value);
table.emplace(key, value);
keys.push_back(key); keys.push_back(key);
} }
TableT table(data.begin(), data.end());
std::size_t key_i = 0; std::size_t key_i = 0;
td::random_shuffle(td::as_mutable_span(keys), rnd); td::random_shuffle(td::as_mutable_span(keys), rnd);