Skip to content

Commit 9ae059b

Browse files
[ADT] Refactor MapVector::insert, try_emplace, and operator[] (NFC) (llvm#155205)
The l-value and r-value reference variants of try_emplace contain nearly identical code. Also, operator[] makes its own call to Map.try_emplace. This patch introduces a templated helper function, try_emplace_impl, and uses it in all of MapVector::insert, try_emplace, and operator[]. The helper function uses perfect forwarding to preserve the exact key type. This patch moves the "private:" section to the end of the class so that the new helper function can use iterator.
1 parent 2e89627 commit 9ae059b

File tree

1 file changed

+26
-33
lines changed

1 file changed

+26
-33
lines changed

llvm/include/llvm/ADT/MapVector.h

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,6 @@ template <typename KeyT, typename ValueT,
3434
typename MapType = DenseMap<KeyT, unsigned>,
3535
typename VectorType = SmallVector<std::pair<KeyT, ValueT>, 0>>
3636
class MapVector {
37-
MapType Map;
38-
VectorType Vector;
39-
40-
static_assert(
41-
std::is_integral_v<typename MapType::mapped_type>,
42-
"The mapped_type of the specified Map must be an integral type");
43-
4437
public:
4538
using key_type = KeyT;
4639
using value_type = typename VectorType::value_type;
@@ -99,13 +92,7 @@ class MapVector {
9992
}
10093

10194
ValueT &operator[](const KeyT &Key) {
102-
std::pair<typename MapType::iterator, bool> Result = Map.try_emplace(Key);
103-
auto &I = Result.first->second;
104-
if (Result.second) {
105-
Vector.push_back(std::make_pair(Key, ValueT()));
106-
I = Vector.size() - 1;
107-
}
108-
return Vector[I].second;
95+
return try_emplace_impl(Key).first->second;
10996
}
11097

11198
// Returns a copy of the value. Only allowed if ValueT is copyable.
@@ -118,33 +105,18 @@ class MapVector {
118105

119106
template <typename... Ts>
120107
std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
121-
auto [It, Inserted] = Map.try_emplace(Key);
122-
if (Inserted) {
123-
It->second = Vector.size();
124-
Vector.emplace_back(std::piecewise_construct, std::forward_as_tuple(Key),
125-
std::forward_as_tuple(std::forward<Ts>(Args)...));
126-
return {std::prev(end()), true};
127-
}
128-
return {begin() + It->second, false};
108+
return try_emplace_impl(Key, std::forward<Ts>(Args)...);
129109
}
130110
template <typename... Ts>
131111
std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
132-
auto [It, Inserted] = Map.try_emplace(Key);
133-
if (Inserted) {
134-
It->second = Vector.size();
135-
Vector.emplace_back(std::piecewise_construct,
136-
std::forward_as_tuple(std::move(Key)),
137-
std::forward_as_tuple(std::forward<Ts>(Args)...));
138-
return {std::prev(end()), true};
139-
}
140-
return {begin() + It->second, false};
112+
return try_emplace_impl(std::move(Key), std::forward<Ts>(Args)...);
141113
}
142114

143115
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
144-
return try_emplace(KV.first, KV.second);
116+
return try_emplace_impl(KV.first, KV.second);
145117
}
146118
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
147-
return try_emplace(std::move(KV.first), std::move(KV.second));
119+
return try_emplace_impl(std::move(KV.first), std::move(KV.second));
148120
}
149121

150122
template <typename V>
@@ -224,6 +196,27 @@ class MapVector {
224196
/// Erase all elements that match \c Pred in a single pass. Takes linear
225197
/// time.
226198
template <class Predicate> void remove_if(Predicate Pred);
199+
200+
private:
201+
MapType Map;
202+
VectorType Vector;
203+
204+
static_assert(
205+
std::is_integral_v<typename MapType::mapped_type>,
206+
"The mapped_type of the specified Map must be an integral type");
207+
208+
template <typename KeyArgT, typename... Ts>
209+
std::pair<iterator, bool> try_emplace_impl(KeyArgT &&Key, Ts &&...Args) {
210+
auto [It, Inserted] = Map.try_emplace(Key);
211+
if (Inserted) {
212+
It->second = Vector.size();
213+
Vector.emplace_back(std::piecewise_construct,
214+
std::forward_as_tuple(std::forward<KeyArgT>(Key)),
215+
std::forward_as_tuple(std::forward<Ts>(Args)...));
216+
return {std::prev(end()), true};
217+
}
218+
return {begin() + It->second, false};
219+
}
227220
};
228221

229222
template <typename KeyT, typename ValueT, typename MapType, typename VectorType>

0 commit comments

Comments
 (0)