FlatHashMap: support initializer_list

This commit is contained in:
Arseny Smirnov 2022-02-08 20:47:10 +01:00
parent d5db554b70
commit d5e163cd9d
2 changed files with 39 additions and 14 deletions

View File

@ -72,7 +72,10 @@ class fixed_vector {
template <class KeyT, class ValueT, class HashT = std::hash<KeyT>> template <class KeyT, class ValueT, class HashT = std::hash<KeyT>>
class FlatHashMapImpl { class FlatHashMapImpl {
public:
struct Node { struct Node {
using first_type = KeyT;
using second_type = ValueT;
KeyT first{}; KeyT first{};
union { union {
ValueT second; ValueT second;
@ -86,6 +89,10 @@ class FlatHashMapImpl {
Node() { Node() {
} }
Node(KeyT key, ValueT value) : first(std::move(key)) {
new (&second) ValueT(std::move(value));
CHECK(!empty());
}
~Node() { ~Node() {
if (!empty()) { if (!empty()) {
second.~ValueT(); second.~ValueT();
@ -127,10 +134,9 @@ class FlatHashMapImpl {
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;
public:
// define key_type and value_type for benchmarks // define key_type and value_type for benchmarks
using key_type = KeyT; using key_type = KeyT;
using value_type = std::pair<const KeyT, ValueT>; using value_type = Node;
struct Iterator { struct Iterator {
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
@ -218,6 +224,18 @@ class FlatHashMapImpl {
assign(other.begin(), other.end()); assign(other.begin(), other.end());
return *this; return *this;
} }
FlatHashMapImpl(std::initializer_list<Node> nodes) {
reserve(nodes.size());
for (auto &node : nodes) {
size_t bucket = calc_bucket(node.key());
while (!nodes_[bucket].empty()) {
next_bucket(bucket);
}
nodes_[bucket].emplace(node.first, node.second);
}
}
FlatHashMapImpl(FlatHashMapImpl &&other) noexcept : nodes_(std::move(other.nodes_)), used_nodes_(other.used_nodes_) { FlatHashMapImpl(FlatHashMapImpl &&other) noexcept : nodes_(std::move(other.nodes_)), used_nodes_(other.used_nodes_) {
other.used_nodes_ = 0; other.used_nodes_ = 0;
} }

View File

@ -11,22 +11,29 @@
#include <array> #include <array>
TEST(FlatHashMap, basic) { TEST(FlatHashMap, basic) {
td::FlatHashMap<int, int> map; {
map[1] = 2; td::FlatHashMap<int, int> map;
ASSERT_EQ(2, map[1]); map[1] = 2;
ASSERT_EQ(1, map.find(1)->first); ASSERT_EQ(2, map[1]);
ASSERT_EQ(2, map.find(1)->second); ASSERT_EQ(1, map.find(1)->first);
// ASSERT_EQ(1, map.find(1)->key()); ASSERT_EQ(2, map.find(1)->second);
// ASSERT_EQ(2, map.find(1)->value()); // ASSERT_EQ(1, map.find(1)->key());
for (auto &kv : map) { // ASSERT_EQ(2, map.find(1)->value());
ASSERT_EQ(1, kv.first); for (auto &kv : map) {
ASSERT_EQ(2, kv.second); ASSERT_EQ(1, kv.first);
ASSERT_EQ(2, kv.second);
}
map.erase(map.find(1));
auto map_copy = map;
} }
map.erase(map.find(1));
auto map_copy = map;
td::FlatHashMap<int, std::array<td::unique_ptr<td::string>, 20>> x; td::FlatHashMap<int, std::array<td::unique_ptr<td::string>, 20>> x;
auto y = std::move(x); auto y = std::move(x);
x[12]; x[12];
x.erase(x.find(12)); x.erase(x.find(12));
{
td::FlatHashMap<int, std::string> map = {{1, "hello"}, {2, "world"}};
ASSERT_EQ("hello", map[1]);
}
} }