Skip to content

Commit 2ee3689

Browse files
Remove std::variant (#23)
1 parent eb6d001 commit 2ee3689

File tree

2 files changed

+45
-31
lines changed

2 files changed

+45
-31
lines changed

phtree/v16/entry.h

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
#include "../../phtree/common/common.h"
2121
#include "node.h"
2222
#include <cassert>
23-
#include <cstdint>
2423
#include <memory>
25-
#include <string>
26-
#include <variant>
24+
#include <optional>
2725

2826
namespace improbable::phtree::v16 {
2927

@@ -44,69 +42,85 @@ class Entry {
4442
using NodeT = Node<DIM, T, SCALAR>;
4543

4644
public:
47-
Entry() : kd_key_(), value_{std::in_place_type<ValueT>, T{}} {}
48-
4945
/*
5046
* Construct entry with existing node.
5147
*/
52-
Entry(const KeyT& k, std::unique_ptr<NodeT>&& node)
53-
: kd_key_{k}
54-
, value_{
55-
std::in_place_type<std::unique_ptr<NodeT>>, std::forward<std::unique_ptr<NodeT>>(node)} {}
48+
Entry(const KeyT& k, std::unique_ptr<NodeT>&& node_ptr)
49+
: kd_key_{k}, node_{std::move(node_ptr)}, value_{std::nullopt} {}
5650

5751
/*
5852
* Construct entry with a new node.
5953
*/
6054
Entry(bit_width_t infix_len, bit_width_t postfix_len)
61-
: kd_key_()
62-
, value_{
63-
std::in_place_type<std::unique_ptr<NodeT>>,
64-
std::make_unique<NodeT>(infix_len, postfix_len)} {}
55+
: kd_key_(), node_{std::make_unique<NodeT>(infix_len, postfix_len)}, value_{std::nullopt} {}
56+
57+
/*
58+
* Construct entry with existing T.
59+
*/
60+
Entry(const KeyT& k, std::optional<ValueT>&& value)
61+
: kd_key_{k}, node_{nullptr}, value_{std::move(value)} {}
6562

6663
/*
6764
* Construct entry with new T or moved T.
6865
*/
6966
template <typename... Args>
7067
explicit Entry(const KeyT& k, Args&&... args)
71-
: kd_key_{k}, value_{std::in_place_type<ValueT>, std::forward<Args>(args)...} {}
68+
: kd_key_{k}, node_{nullptr}, value_{std::in_place, std::forward<Args>(args)...} {}
7269

7370
[[nodiscard]] const KeyT& GetKey() const {
7471
return kd_key_;
7572
}
7673

7774
[[nodiscard]] bool IsValue() const {
78-
return std::holds_alternative<ValueT>(value_);
75+
return value_.has_value();
7976
}
8077

8178
[[nodiscard]] bool IsNode() const {
82-
return std::holds_alternative<std::unique_ptr<NodeT>>(value_);
79+
return node_.get() != nullptr;
8380
}
8481

8582
[[nodiscard]] T& GetValue() const {
8683
assert(IsValue());
87-
return const_cast<T&>(std::get<ValueT>(value_));
84+
return const_cast<T&>(*value_);
8885
}
8986

9087
[[nodiscard]] NodeT& GetNode() const {
9188
assert(IsNode());
92-
return *std::get<std::unique_ptr<NodeT>>(value_);
89+
return *node_;
90+
}
91+
92+
void SetNode(std::unique_ptr<NodeT>&& node) {
93+
assert(!IsNode());
94+
node_ = std::move(node);
95+
value_.reset();
96+
}
97+
98+
[[nodiscard]] std::optional<ValueT>&& ExtractValue() {
99+
assert(IsValue());
100+
return std::move(value_);
101+
}
102+
103+
[[nodiscard]] std::unique_ptr<NodeT>&& ExtractNode() {
104+
assert(IsNode());
105+
return std::move(node_);
93106
}
94107

95108
void ReplaceNodeWithDataFromEntry(Entry&& other) {
96109
assert(IsNode());
97110
kd_key_ = other.GetKey();
98111

99-
// 'value_' points indirectly to 'entry' so we have to remove `entity's` content before
100-
// assigning anything to `value_` here. Otherwise the assignment would destruct the previous
101-
// content and, by reachability, `entity's` content.
102-
auto old_node = std::get<std::unique_ptr<NodeT>>(value_).release();
103-
value_ = std::move(other.value_);
104-
delete old_node;
112+
if (other.IsNode()) {
113+
node_ = std::move(other.node_);
114+
} else {
115+
value_ = std::move(other.value_);
116+
node_.reset();
117+
}
105118
}
106119

107120
private:
108121
KeyT kd_key_;
109-
std::variant<ValueT, std::unique_ptr<NodeT>> value_;
122+
std::unique_ptr<NodeT> node_;
123+
std::optional<ValueT> value_;
110124
};
111125
} // namespace improbable::phtree::v16
112126

phtree/v16/node.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,15 @@ class Node {
285285
return entries_.try_emplace(hc_pos, new_key, std::forward<Args>(args)...).first->second;
286286
}
287287

288-
void WriteEntry(hc_pos_t hc_pos, EntryT&& entry) {
288+
void WriteEntry(hc_pos_t hc_pos, EntryT& entry) {
289289
if (entry.IsNode()) {
290290
auto& node = entry.GetNode();
291291
bit_width_t new_subnode_infix_len = postfix_len_ - node.postfix_len_ - 1;
292292
node.SetInfixLen(new_subnode_infix_len);
293+
entries_.try_emplace(hc_pos, entry.GetKey(), entry.ExtractNode());
294+
} else {
295+
entries_.try_emplace(hc_pos, entry.GetKey(), entry.ExtractValue());
293296
}
294-
entries_.try_emplace(hc_pos, std::move(entry));
295297
}
296298

297299
/*
@@ -356,13 +358,11 @@ class Node {
356358
hc_pos_t pos_sub_2 = CalcPosInArray(current_key, new_postfix_len);
357359

358360
// Move key/value into subnode
359-
new_sub_node->WriteEntry(pos_sub_2, std::move(current_entry));
361+
new_sub_node->WriteEntry(pos_sub_2, current_entry);
360362
auto& new_entry = new_sub_node->WriteValue(pos_sub_1, new_key, std::forward<Args>(args)...);
361363

362364
// Insert new node into local node
363-
// We use new_key because current_key has been moved().
364-
// TODO avoid reassigning the key here, this is unnecessary.
365-
current_entry = {new_key, std::move(new_sub_node)};
365+
current_entry.SetNode(std::move(new_sub_node));
366366
return &new_entry;
367367
}
368368

0 commit comments

Comments
 (0)