Containers

CFlatMap

An ordered map backed by contiguous key and value sequences.

C++23 mc/CFlatMap.h
#include <mc/CFlatMap.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.

keys() returns a const storage reference; keysCopy() returns an independent copy. The legacy allocator template argument remains accepted.

Jump to a declaration · 95

CFlatSequence_

template<class T, class Policy, bool = CAllocator<Policy>> struct CFlatSequence_
template<class T, class Alloc> struct CFlatSequence_<T, Alloc, true>

Types, constants & data

using type = Policy;
using type = std::vector<T, typename std::allocator_traits<Alloc>::template rebind_alloc<T>>;

CFlatAllocator_

template<class T, class Container, class = void> struct CFlatAllocator_
template<class T, class Container> struct CFlatAllocator_<T, Container, std::void_t<typename Container::allocator_type>>

Types, constants & data

using type = std::allocator<T>;
using type = typename std::allocator_traits< typename Container::allocator_type>::template rebind_alloc<T>;

Free functions & types

Types, constants & data

template<class Container> concept CAllocatedContainer = requires(const Container& values){ typename Container::allocator_type; values.get_allocator(); };

Functions

operator==

template<class K, class V, class C, class A, class B> bool operator==(const CFlatMap<K, V, C, A, B>& x, const CFlatMap<K, V, C, A, B>& y);

operator!=

template<class K, class V, class C, class A, class B> bool operator!=(const CFlatMap<K, V, C, A, B>& x, const CFlatMap<K, V, C, A, B>& y);

operator<

template<class K, class V, class C, class A, class B> bool operator<(const CFlatMap<K, V, C, A, B>& x, const CFlatMap<K, V, C, A, B>& y);

operator>

template<class K, class V, class C, class A, class B> bool operator>(const CFlatMap<K, V, C, A, B>& x, const CFlatMap<K, V, C, A, B>& y);

operator<=

template<class K, class V, class C, class A, class B> bool operator<=(const CFlatMap<K, V, C, A, B>& x, const CFlatMap<K, V, C, A, B>& y);

operator>=

template<class K, class V, class C, class A, class B> bool operator>=(const CFlatMap<K, V, C, A, B>& x, const CFlatMap<K, V, C, A, B>& y);

cOutputMap

template<class K, class V, class C, class A, class B> inline void cOutputMap(std::ostream& ostr, const CFlatMap<K, V, C, A, B>& m);

operator<<

template<class K, class V, class C, class A, class B> std::ostream& operator<<(std::ostream& ostr, const CFlatMap<K, V, C, A, B>& m);

operator<=>

template<class K, class V, class C, class A, class B> auto operator<=>(const CFlatMap<K, V, C, A, B>& first, const CFlatMap<K, V, C, A, B>& second);

swap

template<class K, class V, class C, class A, class B> void swap(CFlatMap<K, V, C, A, B>& first, CFlatMap<K, V, C, A, B>& second) noexcept(noexcept(first.swap(second)));

erase_if

template<class K, class V, class C, class A, class B, class Predicate> typename CFlatMap<K, V, C, A, B>::size_type erase_if(CFlatMap<K, V, C, A, B>& map, 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 CFlatMap>

template<class... Args, class S = decltype(std::flat_map(std::declval<Args>()...))> CFlatMap(Args&&...) -> CFlatMap<typename S::key_type, typename S::mapped_type, typename S::key_compare, typename S::key_container_type, typename S::mapped_container_type>;
template<class K, class V, class C = std::less<K>> requires(!CAllocator<C>) CFlatMap(std::initializer_list<std::pair<K, V>>, C = C()) -> CFlatMap<K, V, C>;
template<class K, class V, class C = std::less<K>> requires(!CAllocator<C>) CFlatMap(std::sorted_unique_t, std::initializer_list<std::pair<K, V>>, C = C()) -> CFlatMap<K, V, C>;
template<class K, class V, CAllocator A> CFlatMap(std::initializer_list<std::pair<K, V>>, A) -> CFlatMap<K, V, std::less<K>, typename CFlatSequence_<K, A>::type, typename CFlatSequence_<V, A>::type>;
template<class K, class V, class C, CAllocator A> requires(!CAllocator<C>) CFlatMap(std::initializer_list<std::pair<K, V>>, C, A) -> CFlatMap<K, V, C, typename CFlatSequence_<K, A>::type, typename CFlatSequence_<V, A>::type>;
template<class K, class V, CAllocator A> CFlatMap(std::sorted_unique_t, std::initializer_list<std::pair<K, V>>, A) -> CFlatMap<K, V, std::less<K>, typename CFlatSequence_<K, A>::type, typename CFlatSequence_<V, A>::type>;
template<class K, class V, class C, CAllocator A> requires(!CAllocator<C>) CFlatMap(std::sorted_unique_t, std::initializer_list<std::pair<K, V>>, C, A) -> CFlatMap<K, V, C, typename CFlatSequence_<K, A>::type, typename CFlatSequence_<V, A>::type>;

CFlatMap

template<class K, class V, class Cmp = std::less<K>, class KeyContainer = std::vector<K>, class MappedContainer> class CFlatMap

Types, constants & data

using KeyStorage = typename CFlatSequence_<K, KeyContainer>::type;
using MappedStorage = typename CFlatSequence_<V, std::conditional_t<CAllocator<KeyContainer> && std::same_as<MappedContainer, std::vector<V>>, KeyContainer, MappedContainer>>::type;
using Map = std::flat_map<K, V, Cmp, KeyStorage, MappedStorage>;
using allocator_type = std::conditional_t<CAllocator<KeyContainer>, KeyContainer, typename CFlatAllocator_<std::pair<const K, V>, KeyStorage>::type>;
using key_type = typename Map::key_type;
using mapped_type = typename Map::mapped_type;
using value_type = typename Map::value_type;
using key_compare = typename Map::key_compare;
using value_compare = typename Map::value_compare;
using reference = typename Map::reference;
using const_reference = typename Map::const_reference;
using size_type = typename Map::size_type;
using difference_type = typename Map::difference_type;
using iterator = typename Map::iterator;
using const_iterator = typename Map::const_iterator;
using reverse_iterator = typename Map::reverse_iterator;
using const_reverse_iterator = typename Map::const_reverse_iterator;
using key_container_type = typename Map::key_container_type;
using mapped_container_type = typename Map::mapped_container_type;
using containers = typename Map::containers;
using indexed_type = V&;

Methods

CFlatMap

CFlatMap() noexcept(std::is_nothrow_default_constructible_v<Map>);
explicit CFlatMap(const key_compare& comp);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) explicit CFlatMap(const A& allocator);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(const key_compare& comp, const A& allocator);
CFlatMap(key_container_type keys, mapped_container_type values, const key_compare& comp = cContainerDefault<key_compare>());
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(const key_container_type& keys, const mapped_container_type& values, const A& allocator);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(const key_container_type& keys, const mapped_container_type& values, const key_compare& comp, const A& allocator);
template<CInputIterator I> CFlatMap(I first, I last, const key_compare& comp = cContainerDefault<key_compare>());
template<CInputIterator I, class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(I first, I last, const A& allocator);
template<CInputIterator I, class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(I first, I last, const key_compare& comp, const A& allocator);
CFlatMap(std::initializer_list<value_type> values, const key_compare& comp = cContainerDefault<key_compare>());
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::initializer_list<value_type> values, const A& allocator);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::initializer_list<value_type> values, const key_compare& comp, const A& allocator);
CFlatMap(std::sorted_unique_t, key_container_type keys, mapped_container_type values, const key_compare& comp = cContainerDefault<key_compare>());
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::sorted_unique_t, const key_container_type& keys, const mapped_container_type& values, const A& allocator);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::sorted_unique_t, const key_container_type& keys, const mapped_container_type& values, const key_compare& comp, const A& allocator);
template<CInputIterator I> CFlatMap(std::sorted_unique_t, I first, I last, const key_compare& comp = cContainerDefault<key_compare>());
template<CInputIterator I, class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::sorted_unique_t, I first, I last, const A& allocator);
template<CInputIterator I, class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::sorted_unique_t, I first, I last, const key_compare& comp, const A& allocator);
CFlatMap(std::sorted_unique_t, std::initializer_list<value_type> values, const key_compare& comp = cContainerDefault<key_compare>());
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::sorted_unique_t, std::initializer_list<value_type> values, const A& allocator);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::sorted_unique_t, std::initializer_list<value_type> values, const key_compare& comp, const A& allocator);
template<CContainerRange<value_type> R> CFlatMap(std::from_range_t, R&& range, const key_compare& comp = cContainerDefault<key_compare>());
template<CContainerRange<value_type> R, class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::from_range_t, R&& range, const A& allocator);
template<CContainerRange<value_type> R, class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(std::from_range_t, R&& range, const key_compare& comp, const A& allocator);
CFlatMap(const CFlatMap& other);
CFlatMap(CFlatMap&& other) noexcept(std::is_nothrow_move_constructible_v<Map>);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(const CFlatMap& other, const A& allocator);
template<class A> requires(std::uses_allocator_v<key_container_type, A> && std::uses_allocator_v<mapped_container_type, A>) CFlatMap(CFlatMap&& other, const A& allocator);
CFlatMap(CBuffer& b);

Creates an empty container or builds sorted unique storage from entries. Overloads marked std::sorted_unique require inputs already sorted and unique under the comparator; they do not establish that invariant for the caller. The CBuffer overload restores typed serialized entries.

begin

iterator begin() noexcept;
const_iterator begin() const noexcept;

cbegin

const_iterator cbegin() const noexcept;

end

iterator end() noexcept;
const_iterator end() const noexcept;

cend

const_iterator cend() const noexcept;

rbegin

reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;

crbegin

const_reverse_iterator crbegin() const noexcept;

rend

reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;

crend

const_reverse_iterator crend() const noexcept;

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[]

V& operator[](const key_type& x);
V& operator[](key_type&& k);
template<class Q> requires(CTransparent<key_compare>) mapped_type& operator[](Q&& key);

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

V& at(const key_type& k);
const V& at(const key_type& k) const;
template<class Q> requires(CTransparent<key_compare>) mapped_type& at(const Q& key);
template<class Q> requires(CTransparent<key_compare>) const mapped_type& at(const Q& key) 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

const key_container_type& keys() const noexcept;

Returns a borrowed const reference to the sorted key storage. The same positions in values() hold the corresponding mapped values.

values

const mapped_container_type& values() const noexcept;

Returns a borrowed const reference to mapped-value storage, aligned position-for-position with keys().

find

iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
template<class Q> requires(CTransparent<key_compare>) iterator find(const Q& key);
template<class Q> requires(CTransparent<key_compare>) 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<key_compare>) 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& x) const;
template<class Q> requires(CTransparent<key_compare>) 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.

lower_bound

iterator lower_bound(const key_type& x);
const_iterator lower_bound(const key_type& x) const;
template<class Q> requires(CTransparent<key_compare>) iterator lower_bound(const Q& key);
template<class Q> requires(CTransparent<key_compare>) const_iterator lower_bound(const Q& key) const;

Returns the first position whose key is not less than the requested key according to the ordering policy, or end().

upper_bound

iterator upper_bound(const key_type& x);
const_iterator upper_bound(const key_type& x) const;
template<class Q> requires(CTransparent<key_compare>) iterator upper_bound(const Q& key);
template<class Q> requires(CTransparent<key_compare>) const_iterator upper_bound(const Q& key) const;

Returns the first position whose key is greater than the requested key according to the ordering policy, or end().

equal_range

std::pair<iterator, iterator> equal_range(const key_type& x);
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
template<class Q> requires(CTransparent<key_compare>) std::pair<iterator, iterator> equal_range(const Q& key);
template<class Q> requires(CTransparent<key_compare>) 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& x);
iterator insert(const_iterator position, const value_type& x);
template<class P> requires std::is_constructible_v<value_type, P&&> std::pair<iterator, bool> insert(P&& p);
template<CInputIterator InputIterator> void insert(InputIterator first, InputIterator last);
std::pair<iterator, bool> insert(value_type&& value);
iterator insert(const_iterator hint, value_type&& value);
template<class P> requires(std::is_constructible_v<value_type, P&&>) iterator insert(const_iterator hint, P&& value);
void insert(std::initializer_list<value_type> values);
void insert(std::sorted_unique_t, std::initializer_list<value_type> values);
template<CInputIterator I> void insert(std::sorted_unique_t, I first, I last);

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);
template<class Q, class... Args> requires(CTransparent<key_compare> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) std::pair<iterator, bool> try_emplace(Q&& key, Args&&... args);
template<class Q, class... Args> requires(CTransparent<key_compare> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) iterator try_emplace(const_iterator hint, Q&& 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);
template<class Q, class M> requires(CTransparent<key_compare> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) std::pair<iterator, bool> insert_or_assign(Q&& key, M&& value);
template<class Q, class M> requires(CTransparent<key_compare> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) iterator insert_or_assign(const_iterator hint, Q&& 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.

add

CFlatMap& add(const K& k, const V& t);

Inserts or replaces a mapped value and returns this map for chaining. Unlike insert(), it overwrites an existing value.

init

template<class K2, class V2> V& 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);
size_type erase(const key_type& x);
iterator erase(const_iterator first, const_iterator last);
iterator erase(const_iterator position);
template<class Q> requires(CTransparent<key_compare> && !std::is_convertible_v<Q, iterator> && !std::is_convertible_v<Q, const_iterator>) size_type erase(Q&& key);

Removes the selected position, iterator range, or key. Iterator overloads return the following position; key overloads return the removal count, and shifting storage can invalidate element references.

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).

swap

void swap(CFlatMap& mp) noexcept(noexcept(m_.swap(mp.m_)));

extract

containers extract() &&;

Moves out both key and value containers, leaving this map empty. Call on an rvalue such as std::move(map).extract().

replace

void replace(key_container_type&& keys, mapped_container_type&& values);

Adopts new key and value containers. They must have equal lengths, and keys must already be sorted and unique under this map’s comparator.

merge

template<class C2, class K2, class V2> requires(std::is_copy_constructible_v<K>) void merge(CFlatMap<K, V, C2, K2, V2>& source);
template<class C2, class K2, class V2> requires(std::is_copy_constructible_v<K>) void merge(CFlatMap<K, V, C2, K2, V2>&& 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 CFlatMap& m);

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

outerMerge

void outerMerge(const CFlatMap& 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

const Map& std() const noexcept;
Map& std() noexcept;

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

operator const Map&

operator const Map&() const noexcept;

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

operator Map&

operator Map&() noexcept;

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

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.

std::uses_allocator

template<class K, class V, class C, class KC, class VC, class A> struct uses_allocator<mc::CFlatMap<K, V, C, KC, VC>, A> : uses_allocator<typename mc::CFlatMap<K, V, C, KC, VC>::Map, A>