// Equivalent to std::map, but without operator[] and its bug-prone semantics (in particular, // the implicit insertion of a default-constructed value on failed lookups). template <typename K, typename V, typename Comparator = std::less<K>, typename Allocator = std::allocator<std::pair<const K, V>>> class SafeMap { private: using Self = SafeMap<K, V, Comparator, Allocator>; using Impl = std::map<K, V, Comparator, Allocator>;
public: using key_compare = typename Impl::key_compare; using value_compare = typename Impl::value_compare; using allocator_type = typename Impl::allocator_type; using iterator = typename Impl::iterator; using const_iterator = typename Impl::const_iterator; using size_type = typename Impl::size_type; using key_type = typename Impl::key_type; using value_type = typename Impl::value_type; using node_type = typename Impl::node_type; using insert_return_type = typename Impl::insert_return_type;
// Note that unlike std::map's operator[], this doesn't return a reference to the value.
V Get(const K& k) const {
const_iterator it = map_.find(k);
DCHECK(it != map_.end()); return it->second;
}
// Used to insert a new mapping.
iterator Put(const K& k, const V& v) {
std::pair<iterator, bool> result = map_.emplace(k, v);
DCHECK(result.second); // Check we didn't accidentally overwrite an existing value. return result.first;
}
iterator Put(const K& k, V&& v) {
std::pair<iterator, bool> result = map_.emplace(k, std::move(v));
DCHECK(result.second); // Check we didn't accidentally overwrite an existing value. return result.first;
}
// Used to insert a new mapping at a known position for better performance.
iterator PutBefore(const_iterator pos, const K& k, const V& v) { // Check that we're using the correct position and the key is not in the map.
DCHECK(pos == map_.end() || map_.key_comp()(k, pos->first));
DCHECK(pos == map_.begin() || map_.key_comp()((--const_iterator(pos))->first, k)); return map_.emplace_hint(pos, k, v);
}
iterator PutBefore(const_iterator pos, const K& k, V&& v) { // Check that we're using the correct position and the key is not in the map.
DCHECK(pos == map_.end() || map_.key_comp()(k, pos->first));
DCHECK(pos == map_.begin() || map_.key_comp()((--const_iterator(pos))->first, k)); return map_.emplace_hint(pos, k, std::move(v));
}
// Used to insert a new mapping or overwrite an existing mapping. Note that if the value type // of this container is a pointer, any overwritten pointer will be lost and if this container // was the owner, you have a leak. Returns iterator pointing to the new or overwritten entry.
iterator Overwrite(const K& k, const V& v) {
std::pair<iterator, bool> result = map_.insert(std::make_pair(k, v)); if (!result.second) { // Already there - update the value for the existing key
result.first->second = v;
} return result.first;
}
template <typename CreateFn>
V& GetOrCreate(const K& k, CreateFn&& create) {
static_assert(std::is_same_v<V, std::invoke_result_t<CreateFn>>, "Argument `create` should return a value of type V."); auto lb = lower_bound(k); if (lb != end() && !key_comp()(k, lb->first)) { return lb->second;
} auto it = PutBefore(lb, k, create()); return it->second;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.