Containers

CFlatSet

An ordered set with contiguous storage and set-algebra conveniences.

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

Stores a C++23 std::flat_set. .std() exposes that container by reference; stdCopy() creates an independent copy. The third template argument accepts an allocator (backed by std::vector) or a compatible sequence container.

Rebuild C++ consumers when upgrading from the earlier Boost-backed implementation. container() and get_allocator() have been removed because the standard flat set does not expose these observers. extract() transfers the backing sequence out, and replace() adopts a sorted, unique sequence.

Jump to a declaration · 77

CFlatSet

template <class K, class Cmp = std::less<K>, class Alloc = std::allocator<K>> class CFlatSet

Types, constants & data

using container_type = std::conditional_t<CAllocator<Alloc>, std::vector<K, Alloc>, Alloc>;
using Set = std::flat_set<K, Cmp, container_type>;
using key_type = K;
using value_type = K;
using key_compare = Cmp;
using value_compare = Cmp;
using allocator_type = typename container_type::allocator_type;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = typename Set::size_type;
using difference_type = typename Set::difference_type;
using iterator = typename Set::const_iterator;
using const_iterator = iterator;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = reverse_iterator;
using StandardSet = Set;

Methods

CFlatSet

CFlatSet() noexcept(std::is_nothrow_default_constructible_v<Set>);
explicit CFlatSet(const value_compare& comp);
CFlatSet(const value_compare& comp, const allocator_type& a);
template<CInputIterator InputIterator> CFlatSet(InputIterator first, InputIterator last, const value_compare& comp = cContainerDefault<value_compare>());
template<CInputIterator InputIterator> CFlatSet(InputIterator first, InputIterator last, const value_compare& comp, const allocator_type& a);
CFlatSet(const CFlatSet& s);
CFlatSet(const Set& s);
CFlatSet(CFlatSet&& s) noexcept(std::is_nothrow_move_constructible_v<Set>);
CFlatSet(Set&& s) noexcept(std::is_nothrow_move_constructible_v<Set>);
explicit CFlatSet(const allocator_type& a);
CFlatSet(const CFlatSet& s, const allocator_type& a);
CFlatSet(CFlatSet&& s, const allocator_type& a);
CFlatSet(std::initializer_list<value_type> il, const value_compare& comp = cContainerDefault<value_compare>());
CFlatSet(std::initializer_list<value_type> il, const value_compare& comp, const allocator_type& a);
explicit CFlatSet(container_type values, const key_compare& comp = cContainerDefault<key_compare>());
CFlatSet(const container_type& values, const allocator_type& allocator);
CFlatSet(const container_type& values, const key_compare& comp, const allocator_type& allocator);
template<CInputIterator I> CFlatSet(I first, I last, const allocator_type& allocator);
CFlatSet(std::initializer_list<value_type> values, const allocator_type& allocator);
template<class R> requires(CContainerRange<R, value_type> && !std::same_as<std::remove_cvref_t<R>, container_type> && !std::same_as<std::remove_cvref_t<R>, CFlatSet>) explicit CFlatSet(R&& values, const key_compare& comp = cContainerDefault<key_compare>());
CFlatSet(std::sorted_unique_t, container_type values, const key_compare& comp = cContainerDefault<key_compare>());
CFlatSet(std::sorted_unique_t, const container_type& values, const allocator_type& allocator);
CFlatSet(std::sorted_unique_t, const container_type& values, const key_compare& comp, const allocator_type& allocator);
template<CInputIterator I> CFlatSet(std::sorted_unique_t, I first, I last, const key_compare& comp = cContainerDefault<key_compare>());
template<CInputIterator I> CFlatSet(std::sorted_unique_t, I first, I last, const key_compare& comp, const allocator_type& allocator);
CFlatSet(std::sorted_unique_t, std::initializer_list<value_type> values, const key_compare& comp = cContainerDefault<key_compare>());
CFlatSet(std::sorted_unique_t, std::initializer_list<value_type> values, const key_compare& comp, const allocator_type& allocator);
template<CInputIterator I> CFlatSet(std::sorted_unique_t, I first, I last, const allocator_type& allocator);
CFlatSet(std::sorted_unique_t, std::initializer_list<value_type> values, const allocator_type& allocator);
template<class R> requires(CContainerRange<R, value_type> && !std::same_as<std::remove_cvref_t<R>, container_type> && !std::same_as<std::remove_cvref_t<R>, CFlatSet>) explicit CFlatSet(std::sorted_unique_t, R&& values, const key_compare& comp = cContainerDefault<key_compare>());
template<class R> requires(CContainerRange<R, value_type>) CFlatSet(std::from_range_t, R&& values);
template<class R> requires(CContainerRange<R, value_type>) CFlatSet(std::from_range_t, R&& values, const allocator_type& allocator);
template<class R> requires(CContainerRange<R, value_type>) CFlatSet(std::from_range_t, R&& values, const key_compare& comp);
template<class R> requires(CContainerRange<R, value_type>) CFlatSet(std::from_range_t, R&& values, const key_compare& comp, const allocator_type& allocator);
CFlatSet(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.

range

static CFlatSet range(int64_t a, int64_t b);
static CFlatSet range(size_t size);

Builds the consecutive values in [a, b), or [0, size). An empty interval produces an empty set.

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

const key_type& operator[](size_t i) const;

Returns the element at a zero-based position in iteration order; it is not a key lookup. The position must be valid. For tree and hash sets, finding it requires walking the iterators.

first

const key_type& first() const;
const key_type& first();

Returns the first element in iteration order; the set must be nonempty. For a hash set this is not necessarily the smallest value.

find

iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
template<class K2> requires(CTransparent<key_compare>) iterator find(const K2& x);
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& k) 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& k);
const_iterator lower_bound(const key_type& k) 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& k);
const_iterator upper_bound(const key_type& k) 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& k);
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) 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.

insert

std::pair<iterator, bool> insert(const value_type& v);
std::pair<iterator, bool> insert(value_type&& v);
iterator insert(const_iterator position, const value_type& v);
iterator insert(const_iterator position, value_type&& v);
template<CInputIterator InputIterator> void insert(InputIterator first, InputIterator last);
void insert(std::initializer_list<value_type> il);
template<CInputIterator I> void insert(std::sorted_unique_t, I first, I last);
void insert(std::sorted_unique_t, std::initializer_list<value_type> values);
template<class Q> requires(CTransparent<key_compare> && std::constructible_from<value_type, Q>) std::pair<iterator, bool> insert(Q&& key);
template<class Q> requires(CTransparent<key_compare> && std::constructible_from<value_type, Q>) iterator insert(const_iterator, Q&& key);

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<class R> requires(CContainerRange<R, value_type>) void insert_range(R&& values);

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.

operator<<

template<class S> CFlatSet& operator<<(S&& x);

Inserts one element and returns this set for chaining. Equivalent elements are retained only once.

erase

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<key_compare> && !std::is_convertible_v<Q, iterator>) size_type erase(Q&& key);

Removes a position, iterator range, or key. Iterator overloads return the following position; key overloads return the count, and shifting elements can invalidate references.

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

container_type extract() &&;

Moves out the backing sequence and empties the set. Call on an rvalue such as std::move(set).extract(). The returned sequence retains its allocator and provides normal sequence access.

replace

bool replace(const key_type& xf, const key_type& xr);
bool replace(const key_type& xf, key_type&& xr);
void replace(container_type&& values);

The two-value overload replaces xf with xr when found and returns whether removal occurred. The container overload adopts an already sorted, unique sequence; the caller must maintain that invariant.

intersect

void intersect(const CFlatSet& s);

Replaces this set with the elements shared by both sets. The supplied set is unchanged.

intersects

bool intersects(const CFlatSet& s) const;

Reports whether the sets share any element. The implementation forms an intersection and may allocate temporary storage.

unite

void unite(const CFlatSet& s);

Adds the other set’s elements to this set, retaining each distinct value once. The supplied set is unchanged.

complement

void complement(const CFlatSet& s);

Removes from this set every element present in the supplied set. This is the directional difference: this set minus the argument.

std

Set& std() noexcept;
const Set& 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 Set&

operator Set&() 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 Set&

operator const Set&() const noexcept;

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

stdCopy

StandardSet stdCopy() const requires(std::is_copy_constructible_v<K>);

Copies the underlying std::flat_set, including its comparator. The backing sequence selects its copy allocator using its standard copy-construction rules. Changes to the result do not affect this set.

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

swap

template <class K, class C, class A> void swap(CFlatSet<K, C, A>& x, CFlatSet<K, C, A>& y) noexcept(noexcept(x.swap(y)));

operator<<

template<class K, class C, class A> std::ostream& operator<<(std::ostream& ostr, const CFlatSet<K, C, A>& s);

erase_if

template<class K, class C, class A, class Predicate> typename CFlatSet<K, C, A>::size_type erase_if(CFlatSet<K, C, A>& set, Predicate predicate);

Removes every element for which the predicate returns true and returns the number removed.

<deduction guide for CFlatSet>

template<class... Args, class S = decltype(std::flat_set(std::declval<Args>()...))> CFlatSet(Args&&...) -> CFlatSet<typename S::key_type, typename S::key_compare, typename S::container_type>;
template<class K, class C = std::less<K>> requires(!CAllocator<C>) CFlatSet(std::initializer_list<K>, C = C()) -> CFlatSet<K, C>;
template<class K, class C = std::less<K>> requires(!CAllocator<C>) CFlatSet(std::sorted_unique_t, std::initializer_list<K>, C = C()) -> CFlatSet<K, C>;
template<class K, CAllocator A> CFlatSet(std::initializer_list<K>, A) -> CFlatSet<K, std::less<K>, A>;
template<class K, class C, CAllocator A> CFlatSet(std::initializer_list<K>, C, A) -> CFlatSet<K, C, A>;

std::uses_allocator

template<class K, class C, class A, class Allocator> struct uses_allocator<mc::CFlatSet<K, C, A>, Allocator> : uses_allocator<typename mc::CFlatSet<K, C, A>::container_type, Allocator>