Containers

CHashMap

A hash-based key–value container with unique keys.

C++23 mc/CHashMap.h
#include <mc/CHashMap.h>

Standard-style names retain their familiar container meaning. The notes below explain lookup results, mutation, ownership, and Catalyst conveniences; only entirely obvious operations are left as declarations.

Exceptions escaping container operations are translated to CError. Direct iterator operations, element references, and calls through .std() follow the underlying type’s contracts.

Jump to a declaration · 85

CHashMap

template<class K, class V, class Hash = std::hash<K>, class Pred = std::equal_to<K>, class Alloc = std::allocator<std::pair<const K, V>>> class CHashMap

Types, constants & data

using HashMap = std::unordered_map<K, V, Hash, Pred, Alloc>;
using key_type = typename HashMap::key_type;
using value_type = typename HashMap::value_type;
using allocator_type = typename HashMap::allocator_type;
using reference = typename HashMap::reference;
using const_reference = typename HashMap::const_reference;
using pointer = typename HashMap::pointer;
using const_pointer = typename HashMap::const_pointer;
using size_type = typename HashMap::size_type;
using difference_type = typename HashMap::difference_type;
using iterator = typename HashMap::iterator;
using const_iterator = typename HashMap::const_iterator;
using node_type = typename HashMap::node_type;
using insert_return_type = typename HashMap::insert_return_type;
using mapped_type = typename HashMap::mapped_type;
using hasher = typename HashMap::hasher;
using key_equal = typename HashMap::key_equal;
using local_iterator = typename HashMap::local_iterator;
using const_local_iterator = typename HashMap::const_local_iterator;

Methods

CHashMap

CHashMap() noexcept(std::is_nothrow_default_constructible_v<HashMap>);
explicit CHashMap(size_type n, const hasher& hash = cContainerDefault<hasher>(), const key_equal& equal = cContainerDefault<key_equal>(), const allocator_type& a = cContainerDefault<allocator_type>());
explicit CHashMap(const allocator_type& a);
CHashMap(size_type n, const allocator_type& a);
CHashMap(size_type n, const hasher& hash, const allocator_type& a);
template<CInputIterator I> CHashMap(I first, I last, size_type n = 0, const hasher& hash = cContainerDefault<hasher>(), const key_equal& equal = cContainerDefault<key_equal>(), const allocator_type& a = cContainerDefault<allocator_type>());
template<CInputIterator I> CHashMap(I first, I last, size_type n, const allocator_type& a);
template<CInputIterator I> CHashMap(I first, I last, size_type n, const hasher& hash, const allocator_type& a);
template<CContainerRange<value_type> R> CHashMap(std::from_range_t, R&& range, size_type n = 0, const hasher& hash = cContainerDefault<hasher>(), const key_equal& equal = cContainerDefault<key_equal>(), const allocator_type& a = cContainerDefault<allocator_type>());
template<CContainerRange<value_type> R> CHashMap(std::from_range_t, R&& range, size_type n, const allocator_type& a);
template<CContainerRange<value_type> R> CHashMap(std::from_range_t, R&& range, size_type n, const hasher& hash, const allocator_type& a);
CHashMap(std::initializer_list<value_type> values, size_type n = 0, const hasher& hash = cContainerDefault<hasher>(), const key_equal& equal = cContainerDefault<key_equal>(), const allocator_type& a = cContainerDefault<allocator_type>());
CHashMap(std::initializer_list<value_type> values, size_type n, const allocator_type& a);
CHashMap(std::initializer_list<value_type> values, size_type n, const hasher& hash, const allocator_type& a);
CHashMap(const CHashMap& other);
CHashMap(CHashMap&& other) noexcept(std::is_nothrow_move_constructible_v<HashMap>);
CHashMap(const CHashMap& other, const allocator_type& a);
CHashMap(CHashMap&& other, const allocator_type& a);
CHashMap(const CHashMap&& other);
CHashMap(const HashMap& other);
CHashMap(HashMap&& other) noexcept(std::is_nothrow_move_constructible_v<HashMap>);
CHashMap(const HashMap& other, const allocator_type& a);
CHashMap(HashMap&& other, const allocator_type& a);
CHashMap(const HashMap&& other);
CHashMap(CBuffer& b);

Creates an empty container or copies entries from a range, initializer list, or compatible container. Equivalent keys are stored once. The CBuffer overload restores the corresponding typed container format. Copy constructors preserve the hash function, equality predicate, and maximum load factor. Without an explicit allocator, copying uses select_on_container_copy_construction; allocator-taking copies use the supplied allocator. A failed copy releases partially constructed elements and leaves the source unchanged.

begin

iterator begin() noexcept;
const_iterator begin() const noexcept;
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;

cbegin

const_iterator cbegin() const noexcept;
const_local_iterator cbegin(size_type n) const;

end

iterator end() noexcept;
const_iterator end() const noexcept;
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;

cend

const_iterator cend() const noexcept;
const_local_iterator cend(size_type n) const;

span

cspan span() const noexcept;
cspan span(size_t start) const noexcept;
cspan span(size_t start, size_t endOffset) const noexcept;

Returns numeric indices from zero to size(), optionally excluding an initial or trailing portion. It does not return key/value pairs or an element view.

empty

bool empty() const noexcept;

size

size_type size() const noexcept;

max_size

size_type max_size() const noexcept;

operator[]

mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);

Returns the mapped value by reference, inserting a value-initialized value when the key is missing. Use at() or get() for lookup without insertion.

at

mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;

Returns the mapped value by reference without insertion. A missing key raises COutOfRangeError.

get

V get(const key_type& x, const V& def) const;
V& get(const key_type& x, V& def);

Looks up a key without inserting it. The const overload returns a value copy or fallback; the mutable overload returns a reference to the stored value or the supplied fallback.

keys

template<class T = CVector<K>> T keys() const;

Returns a new vector containing keys in this map’s iteration order. Hash-map order is unspecified.

find

iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal>) iterator find(const Q& key);
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal>) const_iterator find(const Q& key) const;

Returns an iterator to an equivalent key or element, or end() when none is present. This lookup does not insert a missing entry.

has

bool has(const key_type& x) const;

Reports whether an equivalent key or element is present, without inserting anything.

contains

bool contains(const key_type& x) const;
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal>) bool contains(const Q& key) const;

Reports whether an equivalent key is present. This is the standard-style spelling of a membership lookup.

count

size_type count(const key_type& k) const;
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal>) size_type count(const Q& key) const;

Returns the number of elements equivalent to the key. A unique-key container returns either zero or one.

equal_range

std::pair<iterator, iterator> equal_range(const key_type& k);
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal>) std::pair<iterator, iterator> equal_range(const Q& key);
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal>) std::pair<const_iterator, const_iterator> equal_range(const Q& key) const;

Returns the half-open iterator range of equivalent keys. A missing key produces an empty range.

keyForValue

K keyForValue(const V& value);

Scans values and returns the key of the first equal value in iteration order. Raises CError if no value matches.

insert

std::pair<iterator, bool> insert(const value_type& obj);
template<class P> requires std::is_constructible_v<value_type, P&&> std::pair<iterator, bool> insert(P&& obj);
iterator insert(const_iterator hint, const value_type& obj);
template<class P> requires std::is_constructible_v<value_type, P&&> iterator insert(const_iterator hint, P&& obj);
template<CInputIterator InputIterator> void insert(InputIterator first, InputIterator last);
void insert(std::initializer_list<value_type> il);
std::pair<iterator, bool> insert(value_type&& value);
iterator insert(const_iterator hint, value_type&& value);
insert_return_type insert(node_type&& node);
iterator insert(const_iterator hint, node_type&& node);

Inserts entries without replacing an equivalent existing key. For a single value, the pair-returning overload gives an iterator to the existing or inserted entry and a boolean indicating insertion.

insert_range

template<CContainerRange<value_type> R> void insert_range(R&& range);

Inserts elements from a C++ range using the container’s duplicate-key policy. It does not clear the existing contents.

emplace

template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

Constructs an entry from forwarded arguments and attempts insertion. For unique keys, the pair-returning overload reports whether insertion took place; construction may occur even when the key already exists.

emplace_hint

template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);

Attempts emplacement using the supplied position as a lookup hint and returns an iterator to the result. The hint does not change the key ordering or duplicate policy.

try_emplace

template<class... Args> std::pair<iterator, bool> try_emplace(const key_type& key, Args&&... args);
template<class... Args> iterator try_emplace(const_iterator hint, const key_type& key, Args&&... args);
template<class... Args> std::pair<iterator, bool> try_emplace(key_type&& key, Args&&... args);
template<class... Args> iterator try_emplace(const_iterator hint, key_type&& key, Args&&... args);

Constructs the mapped value only if the key is absent. An existing entry is preserved and forwarded value arguments are not moved from in that case.

insert_or_assign

template<class M> std::pair<iterator, bool> insert_or_assign(const key_type& key, M&& value);
template<class M> iterator insert_or_assign(const_iterator hint, const key_type& key, M&& value);
template<class M> std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& value);
template<class M> iterator insert_or_assign(const_iterator hint, key_type&& key, M&& value);

Inserts a missing key or replaces the value of an existing key. The pair-returning overload reports insertion with true and replacement with false.

init

template<class K2, class V2> V2& init(K2&& k, V2&& dv);

Returns the existing mapped value by reference, or inserts dv for a missing key and returns the new value. Existing entries are left unchanged.

erase

iterator erase(iterator position) requires(!std::same_as<iterator, const_iterator>);
iterator erase(const_iterator position);
size_type erase(const key_type& k);
iterator erase(const_iterator first, const_iterator last);
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) size_type erase(Q&& key);

Erases an iterator, a half-open iterator range, or all entries equivalent to a key. Iterator forms return the following iterator; key forms return the number removed.

take

V take(const key_type& k);
V take(const key_type& k, V def);

Moves out the mapped value and erases its key. A missing key raises CError, or returns the fallback when that overload is used.

clear

void clear() noexcept;

clearExcept

template<class S> void clearExcept(const S& s);

Removes entries whose keys are not present in s, as tested by s.has(key).

extract

node_type extract(const_iterator itr);
node_type extract(const key_type& x);
template<class Q> requires(CTransparent<hasher> && CTransparent<key_equal> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) node_type extract(Q&& key);

Detaches one element into an owning node handle without copying its value. Key lookup returns an empty handle if absent; the node may be inserted into a compatible container.

merge

template<class H2, class P2> void merge(CHashMap<K, V, H2, P2, Alloc>& source);
template<class H2, class P2> void merge(CHashMap<K, V, H2, P2, Alloc>&& source);
template<class H2, class P2> void merge(std::unordered_map<K, V, H2, P2, Alloc>& source);
template<class H2, class P2> void merge(std::unordered_map<K, V, H2, P2, Alloc>&& source);
template<class H2, class P2> void merge(std::unordered_multimap<K, V, H2, P2, Alloc>& source);
template<class H2, class P2> void merge(std::unordered_multimap<K, V, H2, P2, Alloc>&& source);

Transfers entries whose keys are absent here from the source. Conflicting entries stay in the source; existing mapped values are preserved.

innerMerge

void innerMerge(const CHashMap& m);

Adds entries whose keys are absent, preserving values already present.

outerMerge

void outerMerge(const CHashMap& m);

Copies incoming entries into this map, replacing values for keys that already exist. The source is unchanged; mapped values are assigned as whole values.

std

HashMap& std() noexcept;
const HashMap& std() const noexcept;

Returns a reference to the underlying container for interoperation. Changes affect this object directly; operations through that reference bypass Catalyst exception translation.

operator HashMap&

operator HashMap&() noexcept;

Borrows the underlying container for interoperability. This does not copy storage; references and iterators follow that container’s lifetime and invalidation rules.

operator const HashMap&

operator const HashMap&() const noexcept;

Borrows the underlying container for interoperability. This does not copy storage; references and iterators follow that container’s lifetime and invalidation rules.

bucket_count

size_type bucket_count() const noexcept;

Returns the current number of hash buckets. Rehashing can change this independently of the element count.

max_bucket_count

size_type max_bucket_count() const noexcept;

Returns the implementation’s upper limit on the number of hash buckets.

bucket_size

size_type bucket_size(size_type n) const;

Returns the number of elements in the specified hash bucket. The bucket index must be below bucket_count().

bucket

size_type bucket(const key_type& k) const;

Returns the hash bucket index for a key, whether or not the key is currently stored.

load_factor

float load_factor() const noexcept;

Returns the average number of elements per hash bucket, size() / bucket_count().

max_load_factor

float max_load_factor() const noexcept;
void max_load_factor(float z);

Reads or sets the load-factor threshold used when growing the hash table. Supply a positive value; lowering it can require a later rehash.

rehash

void rehash(size_type n);

Requests at least the specified number of buckets while satisfying the load-factor requirement. Rehashing invalidates iterators but preserves references to elements.

reserve

void reserve(size_type n);

Reserves hash-table capacity for the requested number of elements under the current maximum load factor. A rehash can invalidate iterators.

store

void store(CBuffer& b) const;

Appends the container to a CBuffer; restore it with the buffer-taking constructor.

dump

cstr dump() const;

Returns the stream-formatted contents as a cstr. Use store() for binary serialization.

Free functions & types

Functions

operator==

template<class K, class V, class H, class P> bool operator==(const CHashMap<K, V, H, P>& x, const CHashMap<K, V, H, P>& y);
template<class K, class V, class H, class P, class A> requires(!std::same_as<A, std::allocator<std::pair<const K, V>>>) bool operator==(const CHashMap<K, V, H, P, A>& x, const CHashMap<K, V, H, P, A>& y);

operator!=

template<class K, class V, class H, class P> bool operator!=(const CHashMap<K, V, H, P>& x, const CHashMap<K, V, H, P>& y);
template<class K, class V, class H, class P, class A> requires(!std::same_as<A, std::allocator<std::pair<const K, V>>>) bool operator!=(const CHashMap<K, V, H, P, A>& x, const CHashMap<K, V, H, P, A>& y);

operator<

template<class K, class V, class H, class P> bool operator<(const CHashMap<K, V, H, P>& x, const CHashMap<K, V, H, P>& y);
template<class K, class V, class H, class P, class A> requires(!std::same_as<A, std::allocator<std::pair<const K, V>>>) bool operator<(const CHashMap<K, V, H, P, A>& x, const CHashMap<K, V, H, P, A>& y);

operator>

template<class K, class V, class H, class P> bool operator>(const CHashMap<K, V, H, P>& x, const CHashMap<K, V, H, P>& y);
template<class K, class V, class H, class P, class A> requires(!std::same_as<A, std::allocator<std::pair<const K, V>>>) bool operator>(const CHashMap<K, V, H, P, A>& x, const CHashMap<K, V, H, P, A>& y);

operator<=

template<class K, class V, class H, class P> bool operator<=(const CHashMap<K, V, H, P>& x, const CHashMap<K, V, H, P>& y);
template<class K, class V, class H, class P, class A> requires(!std::same_as<A, std::allocator<std::pair<const K, V>>>) bool operator<=(const CHashMap<K, V, H, P, A>& x, const CHashMap<K, V, H, P, A>& y);

operator>=

template<class K, class V, class H, class P> bool operator>=(const CHashMap<K, V, H, P>& x, const CHashMap<K, V, H, P>& y);
template<class K, class V, class H, class P, class A> requires(!std::same_as<A, std::allocator<std::pair<const K, V>>>) bool operator>=(const CHashMap<K, V, H, P, A>& x, const CHashMap<K, V, H, P, A>& y);

cOutputMap

template<class K, class V, class H, class P, class A> inline void cOutputMap(std::ostream& ostr, const CHashMap<K, V, H, P, A>& m);

operator<<

template<class K, class V, class H, class P, class A> std::ostream& operator<<(std::ostream& ostr, const CHashMap<K, V, H, P, A>& m);

swap

template<class K, class V, class H, class P, class A> void swap(CHashMap<K, V, H, P, A>& x, CHashMap<K, V, H, P, A>& y) noexcept(noexcept(x.swap(y)));

erase_if

template<class K, class V, class H, class P, class A, class Predicate> typename CHashMap<K, V, H, P, A>::size_type erase_if(CHashMap<K, V, H, P, A>& container, Predicate predicate);

Removes every element for which the predicate returns true and returns the number removed. Map predicates receive key/value entries.

<deduction guide for CHashMap>

template<class... Args, class S = decltype(std::unordered_map(std::declval<Args>()...))> CHashMap(Args&&...) -> CHashMap< typename S::key_type, typename S::mapped_type, typename S::hasher, typename S::key_equal, typename S::allocator_type>;
template<class K, class V, class H = std::hash<K>, class P = std::equal_to<K>, CAllocator A = std::allocator<std::pair<const K, V>>> requires(!std::is_integral_v<H> && !CAllocator<H> && !CAllocator<P>) CHashMap(std::initializer_list<std::pair<K, V>>, size_t = 0, H = H(), P = P(), A = A()) -> CHashMap<std::remove_const_t<K>, V, H, P, A>;
template<class K, class V, CAllocator A> CHashMap(std::initializer_list<std::pair<K, V>>, size_t, A) -> CHashMap<std::remove_const_t<K>, V, std::hash<K>, std::equal_to<K>, A>;
template<class K, class V, class H, CAllocator A> requires(!std::is_integral_v<H> && !CAllocator<H>) CHashMap(std::initializer_list<std::pair<K, V>>, size_t, H, A) -> CHashMap<std::remove_const_t<K>, V, H, std::equal_to<K>, A>;

pmr

Types, constants & data

template<class K, class V, class H = std::hash<K>, class P = std::equal_to<K>> using CHashMap = mc::CHashMap<K, V, H, P, std::pmr::polymorphic_allocator<std::pair<const K, V>>>;