Files
TheRock/rocm-systems/projects/rocprofiler-systems/external/dyninst/dataflowAPI/rose/util/Map.h
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

691 lines
31 KiB
C++

// WARNING: Changes to this file must be contributed back to Sawyer or else they will
// be clobbered by the next update from Sawyer. The Sawyer repository is at
// https://github.com/matzke1/sawyer.
#ifndef Sawyer_Map_H
#define Sawyer_Map_H
#include "Interval.h"
#include "Optional.h"
#include "Sawyer.h"
#include <memory>
#include <stddef.h>
#include <utility>
#include <dyncompat/range/iterator_range.hpp>
#include <map>
#include <stdexcept>
namespace Sawyer {
/** %Container classes that store user-defined values.
*
* This library implements a number of container classes. In general, these classes adhere to the naming scheme used
* throughout the library, which might be somewhat surprising compared with STL containers. The major differences are:
*
* @li All type names are CamelCase with an initial capital letter, such as <code>Iterator</code>, <code>ConstIterator</code>,
* etc.
* @li Some containers have multiple categories of iterator, such as iterators that visit the storage nodes of the container,
* and iterators that visit the values logically contained in the container. For instance one can iterate over the keys
* alone in a key/value map, or the values alone, or the combined storage nodes that have a key/value pair.
* @li The containers have no direct <code>begin</code> and <code>end</code> methods, but rather return iterator ranges with
* methods like, for the key/value map container, <code>keys</code>, <code>values</code>, and <code>nodes</code>. This
* allows containers return different types of iterators. The iterator ranges have the usual <code>begin</code> and
* <code>end</code> methods.
* @li Most predicates start with the word "is", such as <code>isEmpty</code> so they cannot be confused with a similar verb
* (i.e., it is quite obvious that <code>isEmpty</code> does not empty the container).
* @li The <code>insert</code> methods come in different flavors depending on what's being inserted. Inserters that insert
* a value are named <code>insert</code>; those that insert multiple values, like from another container or iterator
* range, are named <code>insertMultiple</code>. This gives the API more flexibility and consistency across different
* containers.
* @li The <code>erase</code> methods also come in different flavors: <code>erase</code> is to erase a single specified value,
* <code>eraseAt</code> is for erasing based on location (i.e., iterators that point into that container), and
* <code>eraseMultiple</code> is to erase multiple values at once (e.g., values obtained from a different container).
* As with <code>insert</code>, this gives container designers more flexibility and at the same time improves
* consistency. */
namespace Container {
/** %Container associating values with keys.
*
* This container is similar to the <code>std::map</code> container in the standard template library, but with these
* differences in addition to those described in the documentation for the Sawyer::Container name space:
*
* @li It extends the interface with additional methods that return optional values (@ref Optional) and a few
* convenience methods (like @ref exists).
* @li It provides iterators over keys and values in addition to the STL-like iterator over nodes.
* @li The insert methods always insert the specified value(s) regardless of whether a node with the same key already
* existed (i.e., they do what their name says they do). If you need STL behavior, then use the <code>insertMaybe</code>
* methods. */
template<class K,
class T,
class Cmp = std::less<K>,
class Alloc = std::allocator<std::pair<const K, T> > >
class Map {
public:
typedef K Key; /**< Type for keys. */
typedef T Value; /**< Type for values associated with each key. */
typedef Cmp Comparator; /**< Type of comparator, third template argument. */
typedef Alloc Allocator; /**< Type of allocator, fourth template argument. */
private:
typedef std::map<Key, Value, Comparator, Alloc> StlMap;
StlMap map_;
public:
/** Type for stored nodes.
*
* A storage node contains the immutable key and its associated value. */
class Node: private std::pair<const Key, Value> {
// This class MUST BE binary compatible with its super class (see NodeIterator::operator* below)
public:
explicit Node(const std::pair<const Key, Value> &pair): std::pair<const Key, Value>(pair) {}
Node(const Key &key, Value &value): std::pair<const Key, Value>(key, value) {}
public:
/** Key part of key/value node.
*
* Returns the key part of a key/value node. Keys are not mutable when they are part of a map. */
const Key& key() const { return this->first; }
/** Value part of key/value node.
*
* Returns a reference to the value part of a key/value node.
*
* @{ */
Value& value() { return this->second; }
const Value& value() const { return this->second; }
/** @} */
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Iterators
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private:
template<class Derived, class Value, class BaseIterator>
class BidirectionalIterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = Value;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
protected:
BaseIterator base_;
BidirectionalIterator() {}
BidirectionalIterator(const BaseIterator &base): base_(base) {}
public:
Derived& operator=(const Derived &other) { base_ = other.base_; return *derived(); }
Derived& operator++() { ++base_; return *derived(); }
Derived operator++(int) { Derived old=*derived(); ++*this; return old; }
Derived& operator--() { --base_; return *derived(); }
Derived operator--(int) { Derived old=*derived(); --*this; return old; }
template<class OtherIter> bool operator==(const OtherIter &other) const { return base_ == other.base(); }
template<class OtherIter> bool operator!=(const OtherIter &other) const { return base_ != other.base(); }
const BaseIterator& base() const { return base_; }
protected:
Derived* derived() { return static_cast<Derived*>(this); }
const Derived* derived() const { return static_cast<const Derived*>(this); }
};
public:
/** Bidirectional iterator over key/value nodes.
*
* Dereferencing this iterator will return a Node from which both the key and the value can be obtained. Node iterators
* are implicitly convertible to both key and value iterators. */
class NodeIterator: public BidirectionalIterator<NodeIterator, Node, typename StlMap::iterator> {
typedef BidirectionalIterator<NodeIterator, Node, typename StlMap::iterator> Super;
public:
NodeIterator() {}
// std::map stores std::pair nodes, but we want to return Node, which must have the same layout.
Node& operator*() const { return *(Node*)&*this->base_; }
Node* operator->() const { return (Node*)&*this->base_; }
private:
friend class Map;
NodeIterator(const typename StlMap::iterator &base): Super(base) {}
};
/** Bidirectional iterator over key/value nodes.
*
* Dereferencing this iterator will return a Node from which both the key and the value can be obtained. Node iterators
* are implicitly convertible to both key and value iterators. */
class ConstNodeIterator: public BidirectionalIterator<ConstNodeIterator, const Node, typename StlMap::const_iterator> {
typedef BidirectionalIterator<ConstNodeIterator, const Node, typename StlMap::const_iterator> Super;
public:
ConstNodeIterator() {}
ConstNodeIterator(const ConstNodeIterator &other): Super(other) {}
ConstNodeIterator(const NodeIterator &other): Super(typename StlMap::const_iterator(other.base())) {}
// std::map stores std::pair nodes, but we want to return Node, which must have the same layout.
const Node& operator*() const { return *(const Node*)&*this->base_; }
const Node* operator->() const { return (const Node*)&*this->base_; }
private:
friend class Map;
ConstNodeIterator(const typename StlMap::const_iterator &base): Super(base) {}
ConstNodeIterator(const typename StlMap::iterator &base): Super(typename StlMap::const_iterator(base)) {}
};
/** Bidirectional iterator over keys.
*
* Dereferencing this iterator will return a reference to a const key. Keys cannot be altered while they are a member of
* this container. */
class ConstKeyIterator: public BidirectionalIterator<ConstKeyIterator, const Key, typename StlMap::const_iterator> {
typedef BidirectionalIterator<ConstKeyIterator, const Key, typename StlMap::const_iterator> Super;
public:
ConstKeyIterator() {}
ConstKeyIterator(const ConstKeyIterator &other): Super(other) {}
ConstKeyIterator(const NodeIterator &other): Super(typename StlMap::const_iterator(other.base())) {}
ConstKeyIterator(const ConstNodeIterator &other): Super(other.base()) {}
const Key& operator*() const { return this->base()->first; }
const Key* operator->() const { return &this->base()->first; }
};
/** Bidirectional iterator over values.
*
* Dereferencing this iterator will return a reference to the user-defined value of the node. Values may be altered
* in-place while they are members of a container. */
class ValueIterator: public BidirectionalIterator<ValueIterator, Value, typename StlMap::iterator> {
typedef BidirectionalIterator<ValueIterator, Value, typename StlMap::iterator> Super;
public:
ValueIterator() {}
ValueIterator(const ValueIterator &other): Super(other) {}
ValueIterator(const NodeIterator &other): Super(other.base()) {}
Value& operator*() const { return this->base()->second; }
Value* operator->() const { return &this->base()->second; }
};
/** Bidirectional iterator over values.
*
* Dereferencing this iterator will return a reference to the user-defined value of the node. Values may be altered
* in-place while they are members of a container. */
class ConstValueIterator: public BidirectionalIterator<ConstValueIterator, const Value, typename StlMap::const_iterator> {
typedef BidirectionalIterator<ConstValueIterator, const Value, typename StlMap::const_iterator> Super;
public:
ConstValueIterator() {}
ConstValueIterator(const ConstValueIterator &other): Super(other) {}
ConstValueIterator(const ValueIterator &other): Super(typename StlMap::const_iterator(other.base())) {}
ConstValueIterator(const ConstNodeIterator &other): Super(other.base()) {}
ConstValueIterator(const NodeIterator &other): Super(typename StlMap::const_iterator(other.base())) {}
const Value& operator*() const { return this->base()->second; }
const Value* operator->() const { return &this->base()->second; }
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructors
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
/** Default constructor.
*
* Creates an empty map. */
Map() {}
/** Constructs an empty map.
*
* This is like the default constructor, but a comparer and allocator can be specified. */
explicit Map(const Comparator &comparator, const Allocator &allocator = Allocator())
: map_(comparator, allocator) {}
/** Copy constructor. */
Map(const Map& other) {
map_ = other.map_;
}
/** Copy constructor.
*
* Initializes the new map with copies of the nodes of the @p other map. The keys and values must be convertible from the
* other map to this map. */
template<class Key2, class T2, class Cmp2, class Alloc2>
Map(const Map<Key2, T2, Cmp2, Alloc2> &other) {
typedef typename Map<Key2, T2, Cmp2, Alloc2>::ConstNodeIterator OtherIterator;
dyncompat::iterator_range<OtherIterator> otherNodes = other.nodes();
for (OtherIterator otherIter=otherNodes.begin(); otherIter!=otherNodes.end(); ++otherIter)
map_.insert(map_.end(), std::make_pair(Key(otherIter->key()), Value(otherIter->value())));
}
/** Make this map be a copy of another map.
*
* The keys and values of the @p other map must be convertible to the types used for this map. */
template<class Key2, class T2, class Cmp2, class Alloc2>
Map& operator=(const Map<Key2, T2, Cmp2, Alloc2> &other) {
typedef typename Map<Key2, T2, Cmp2, Alloc2>::ConstNodeIterator OtherIterator;
clear();
dyncompat::iterator_range<OtherIterator> otherNodes = other.nodes();
for (OtherIterator otherIter=otherNodes.begin(); otherIter!=otherNodes.end(); ++otherIter)
map_.insert(map_.end(), std::make_pair(Key(otherIter->key()), Value(otherIter->value())));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Iteration
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
/** Iterators for container nodes.
*
* This returns a range of node-iterators that will traverse all nodes (key/value pairs) of this container.
*
* @{ */
dyncompat::iterator_range<NodeIterator> nodes() {
return dyncompat::iterator_range<NodeIterator>(NodeIterator(map_.begin()), NodeIterator(map_.end()));
}
dyncompat::iterator_range<ConstNodeIterator> nodes() const {
return dyncompat::iterator_range<ConstNodeIterator>(ConstNodeIterator(map_.begin()), ConstNodeIterator(map_.end()));
}
/** @} */
/** Iterators for container keys.
*
* Returns a range of key-iterators that will traverse the keys of this container.
*
* @{ */
dyncompat::iterator_range<ConstKeyIterator> keys() {
return dyncompat::iterator_range<ConstKeyIterator>(NodeIterator(map_.begin()), NodeIterator(map_.end()));
}
dyncompat::iterator_range<ConstKeyIterator> keys() const {
return dyncompat::iterator_range<ConstKeyIterator>(ConstNodeIterator(map_.begin()), ConstNodeIterator(map_.end()));
}
/** @} */
/** Iterators for container values.
*
* Returns a range of iterators that will traverse the user-defined values of this container. The values are iterated in
* key order, although the keys are not directly available via these iterators.
*
* @{ */
dyncompat::iterator_range<ValueIterator> values() {
return dyncompat::iterator_range<ValueIterator>(NodeIterator(map_.begin()), NodeIterator(map_.end()));
}
dyncompat::iterator_range<ConstValueIterator> values() const {
return dyncompat::iterator_range<ConstValueIterator>(ConstNodeIterator(map_.begin()), ConstNodeIterator(map_.end()));
}
/** @} */
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Size and capacity
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
/** Determines whether this container is empty.
*
* Returns true if the container is empty, and false if it has at least one node. This method executes in constant time. */
bool isEmpty() const {
return map_.empty();
}
/** Number of nodes, keys, or values in this container.
*
* Returns the number of nodes (elements) in this container. This method executes in constant time. */
size_t size() const {
return map_.size();
}
/** Returns the minimum key. The map must not be empty. */
Key least() const {
ASSERT_forbid(isEmpty());
return map_.begin()->first;
}
/** Returns the maximum key. The map must not be empty. */
Key greatest() const {
ASSERT_forbid(isEmpty());
typename StlMap::const_iterator last = map_.end();
--last;
return last->first;
}
/** Returns the range of keys in this map.
*
* The return value is an interval containing the least and greatest keys, inclusive. If the map is empty then an empty
* interval is returned.
*
* This method is only defined when the map key type is appropriate for the Interval class template (such as when the keys
* are an integer type). */
Interval<Key> hull() const {
return isEmpty() ? Interval<Key>() : Interval<Key>::hull(least(), greatest());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Searching
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
/** Find a node by key.
*
* Looks for a node whose key is equal to the specified @p key and returns an iterator to that node, or the end
* iterator if no such node exists. Two keys are considered equal if this container's Comparator object returns false
* reflexively. The method executes logorithmic time based on the number of nodes in the container.
*
* @{ */
NodeIterator find(const Key &key) {
return map_.find(key);
}
ConstNodeIterator find(const Key &key) const {
return map_.find(key);
}
/** @} */
/** Determine if a key exists.
*
* Looks for a node whose key is equal to the specified @p key and returns true if found, or false if no such node exists.
* Two keys are considered equal if this container's @ref Comparator object returns false reflexively. The method executes
* in logorithmic time based on the number of nodes in the container. */
bool exists(const Key &key) const {
return map_.find(key)!=map_.end();
}
/** Find a node close to a key.
*
* Finds the first node whose key is equal to or larger than the specified key and returns an iterator to that node. If no
* such node exists, then the end iterator is returned. The internal @ref Comparator object is used to make the
* comparison. This method executes in logorithmic time based on the number of nodes in the container.
*
* @sa upperBound
*
* @{ */
NodeIterator lowerBound(const Key &key) {
return map_.lower_bound(key);
}
ConstNodeIterator lowerBound(const Key &key) const {
return map_.lower_bound(key);
}
/** @} */
/** Find a node close to a key.
*
* Finds the first node whose key is larger than the specified key and returns an iterator to that node. If no such node
* exists, then the end iterator is returned. The internal @ref Comparator object is used to make the
* comparison. This method executes in logorithmic time based on the number of nodes in the container.
*
* @sa lowerBound
*
* @{ */
NodeIterator upperBound(const Key &key) {
return map_.upper_bound(key);
}
ConstNodeIterator upperBound(const Key &key) const {
return map_.upper_bound(key);
}
/** @} */
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Accessors
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
/** Return a reference to an existing value.
*
* Returns a reference to the value at the node with the specified @p key. Unlike <code>std::map</code>, this container
* does not instantiate a new key/value pair if the @p key is not in the map's domain. In other words, the array operator
* for this class is more like an array operator on arrays or vectors--such objects are not automatically extended if
* dereferenced with an operand that is outside the domain.
*
* If the @p key is not part of this map's domain then an <code>std:domain_error</code> is thrown.
*
* @sa insert insertDefault
*
* @{ */
Value& operator[](const Key &key) {
return get(key);
}
const Value& operator[](const Key &key) const {
return get(key);
}
/** @} */
/** Lookup and return an existing value.
*
* Returns a reference to the value at the node with the specified @p key, which must exist. If the @p key is not part of
* this map's domain then an <code>std:domain_error</code> is thrown.
*
* @sa insert insertDefault
*
* @{ */
Value& get(const Key &key) {
typename StlMap::iterator found = map_.find(key);
if (found==map_.end())
throw std::domain_error("key lookup failure; key is not in map domain");
return found->second;
}
const Value& get(const Key &key) const {
typename StlMap::const_iterator found = map_.find(key);
if (found==map_.end())
throw std::range_error("key lookup failure; key is not in map domain");
return found->second;
}
/** @} */
/** Lookup and return a value or nothing.
*
* Looks up the node with the specified key and returns either a copy of its value, or nothing. This method executes in
* logorithmic time.
*
* Here's an example of one convenient way to use this:
*
* @code
* Map<std::string, FileInfo> files;
* ...
* if (Optional<FileInfo> fileInfo = files.getOptional(fileName))
* std::cout <<"file info for \"" <<fileName <<"\" is " <<*fileInfo <<"\n";
* @endcode
*
* The equivalent STL approach is:
*
* @code
* std::map<std::string, FileInfo> files;
* ...
* std::map<std::string, FileInfo>::const_iterator filesIter = files.find(fileName);
* if (fileIter != files.end())
* std::cout <<"file info for \"" <<fileName <<"\" is " <<filesIter->second <<"\n";
* @endcode */
Optional<Value> getOptional(const Key &key) const {
typename StlMap::const_iterator found = map_.find(key);
return found == map_.end() ? Optional<Value>() : Optional<Value>(found->second);
}
/** Lookup and return a value or something else.
*
* This is similar to the @ref get method, except a default can be provided. If a node with the specified @p key is
* present in this container, then a reference to that node's value is returned, otherwise the (reference to) supplied
* default is returned.
*
* @{ */
Value& getOrElse(const Key &key, Value &dflt) {
typename StlMap::iterator found = map_.find(key);
return found == map_.end() ? dflt : found->second;
}
const Value& getOrElse(const Key &key, const Value &dflt) const {
typename StlMap::const_iterator found = map_.find(key);
return found == map_.end() ? dflt : found->second;
}
/** @} */
/** Lookup and return a value or a default.
*
* This is similar to the @ref getOrElse method except when the key is not present in the map, a reference to a const,
* default-constructed value is returned. */
const Value& getOrDefault(const Key &key) const {
static const Value dflt;
typename StlMap::const_iterator found = map_.find(key);
return found==map_.end() ? dflt : found->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mutators
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
/** Insert or update a key/value pair.
*
* Inserts the key/value pair into the container. If a previous node already had the same key then it is replaced by the
* new node. This method executes in logorithmic time.
*
* @sa insertDefault insertMaybe insertMaybeDefault insertMultiple insertMaybeMultiple */
Map& insert(const Key &key, const Value &value) {
std::pair<typename StlMap::iterator, bool> inserted = map_.insert(std::make_pair(key, value));
if (!inserted.second)
inserted.first->second = value;
return *this;
}
/** Insert or update a key with a default value.
*
* The value associated with @p key in the map is replaced with a default-constructed value. If the key does not exist
* then it is inserted with a default value. This operation is similar to the array operator of <code>std::map</code>.
*
* @sa insert insertMaybe insertMaybeDefault insertMultiple insertMaybeMultiple */
Map& insertDefault(const Key &key) {
map_[key] = T();
return *this;
}
/** Insert multiple values.
*
* Inserts copies of the nodes in the specified node iterator range. The iterators must iterate over objects that have
* <code>key</code> and <code>value</code> methods that return keys and values that are convertible to the types used by
* this container.
*
* The normal way to insert the contents of one map into another is:
*
* @code
* Map<...> source = ...;
* Map<...> destination = ...;
* destination.insertMultiple(source.nodes());
* @endcode
*
* @sa insert insertDefault insertMaybe insertMaybeDefault insertMaybeMultiple
*
* @{ */
template<class OtherNodeIterator>
Map& insertMultiple(const OtherNodeIterator &begin, const OtherNodeIterator &end) {
for (OtherNodeIterator otherIter=begin; otherIter!=end; ++otherIter)
insert(Key(otherIter->key()), Value(otherIter->value()));
return *this;
}
template<class OtherNodeIterator>
Map& insertMultiple(const dyncompat::iterator_range<OtherNodeIterator> &range) {
return insertMultiple(range.begin(), range.end());
}
/** @} */
/** Conditionally insert a new key/value pair.
*
* Inserts the key/value pair into the container if the container does not yet have a node with the same key. This method
* executes in logarithmic time. The return value is a reference to the value that is in the container, either the value
* that previously existed or a copy of the specified @p value.
*
* @sa insert insertDefault insertMaybeDefault insertMultiple insertMaybeMultiple */
Value& insertMaybe(const Key &key, const Value &value) {
return map_.insert(std::make_pair(key, value)).first->second;
}
/** Conditionally insert a new key with default value.
*
* Inserts a key/value pair into the container if the container does not yet have a node with the same key. The value is
* default-constructed. This method executes in logarithmic time. The return value is a reference to the value that is
* in the container, either the value that previously existed or the new default-constructed value.
*
* @sa insert insertDefault insertMultiple insertMaybeMultiple */
Value& insertMaybeDefault(const Key &key) {
return map_.insert(std::make_pair(key, T())).first->second;
}
/** Conditionally insert multiple key/value pairs.
*
* Inserts each of the specified key/value pairs into this container where this container does not already contain a value
* for the key. The return value is a reference to the container itself so that this method can be chained with others.
*
* @sa insert insertDefault insertMaybe insertMaybeDefault insertMultiple */
template<class OtherNodeIterator>
Map& insertMaybeMultiple(const dyncompat::iterator_range<OtherNodeIterator> &range) {
for (OtherNodeIterator otherIter=range.begin(); otherIter!=range.end(); ++otherIter)
insert(Key(otherIter->key()), Value(otherIter->value()));
return *this;
}
/** Remove all nodes.
*
* All nodes are removed from this container. This method executes in linear time in the number of nodes in this
* container. */
Map& clear() {
map_.clear();
return *this;
}
/** Remove a node with specified key.
*
* Removes the node whose key is equal to the specified key, or does nothing if no such node exists. Two keys are
* considered equal if this container's @ref Comparator object returns false reflexively. The method executes in
* logorithmic time based on the number of nodes in the container.
*
* @sa eraseMultiple eraseAt eraseAtMultiple */
Map& erase(const Key &key) {
map_.erase(key);
return *this;
}
/** Remove keys stored in another Map.
*
* All nodes of this container whose keys are equal to any key in the @p other container are removed from this container.
* The keys of the other container must be convertible to the types used by this container, and two keys are considered
* equal if this container's @ref Comparator object returns false reflexively. The method executes in <em>N log(N+M)</em>
* time.
*
* @sa erase eraseAt eraseAtMultiple */
template<class OtherKeyIterator>
Map& eraseMultiple(const dyncompat::iterator_range<OtherKeyIterator> &range) {
for (OtherKeyIterator otherIter=range.begin(); otherIter!=range.end(); ++otherIter)
map_.erase(Key(*otherIter));
return *this;
}
/** Remove a node by iterator.
*
* Removes the node referenced by @p iter. The iterator must reference a valid node in this container.
*
* @sa erase eraseMultiple eraseAtMultiple
*
* @{ */
Map& eraseAt(const NodeIterator &iter) {
map_.erase(iter.base());
return *this;
}
Map& eraseAt(const ConstKeyIterator &iter) {
map_.erase(iter.base());
return *this;
}
Map& eraseAt(const ValueIterator &iter) {
map_.erase(iter.base());
return *this;
}
/** @} */
/** Remove multiple nodes by iterator range.
*
* The iterator range must contain iterators that point into this container.
*
* @sa erase eraseAt eraseMultiple
*
* @{ */
template<class Iter>
Map& eraseAtMultiple(const Iter &begin, const Iter &end) {
map_.erase(begin.base(), end.base());
return *this;
}
template<class Iter>
Map& eraseAtMultiple(const dyncompat::iterator_range<Iter> &range) {
map_.erase(range.begin().base(), range.end().base());
return *this;
}
/** @} */
};
} // namespace
} // namespace
#endif