An associative container with contiguous, predictable storage. More...
#include <bio/ranges/container/dictionary.hpp>
Public Types | |
Associated types | |
using | mapped_ref_t = std::conditional_t< mapped_t_is_context_aware, mapped_t const &, mapped_t & > |
Usually mapped_t & . | |
using | value_type = std::tuple< key_t, mapped_t > |
The value_type type. | |
using | reference = std::tuple< key_t const &, mapped_ref_t > |
The reference type. | |
using | const_reference = std::tuple< key_t const &, mapped_t const & > |
The const_reference type. | |
using | difference_type = ptrdiff_t |
The difference_type type. | |
using | size_type = size_t |
The size_type type. | |
using | const_iterator = detail::random_access_iterator< dictionary const > |
The const_iterator type. | |
using | iterator = std::conditional_t< mapped_t_is_context_aware, const_iterator, detail::random_access_iterator< dictionary > > |
Public Member Functions | |
Constructors, destructor and assignment | |
dictionary ()=default | |
Defaulted. | |
dictionary (dictionary const &)=default | |
Defaulted. | |
dictionary (dictionary &&) noexcept=default | |
Defaulted. | |
dictionary & | operator= (dictionary const &)=default |
Defaulted. | |
dictionary & | operator= (dictionary &&) noexcept=default |
Defaulted. | |
~dictionary ()=default | |
Defaulted. | |
template<typename... value_type_> requires ((std::convertible_to<value_type_, value_type> && ...) && sizeof...(value_type_) > 0) | |
dictionary (value_type_ &&... args) | |
Construct from a list of values of value_type. | |
template<meta::different_from< iterator > begin_it_type, typename end_it_type > requires (meta::different_from<const_iterator, begin_it_type> && std::forward_iterator<begin_it_type> && std::sentinel_for<end_it_type, begin_it_type> && std::convertible_to<std::iter_reference_t<begin_it_type>, value_type>) | |
dictionary (begin_it_type const begin_it, end_it_type const end_it) | |
Construct from two iterators. | |
dictionary (iterator const begin_it, iterator const end_it) | |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
dictionary (const_iterator const begin_it, const_iterator const end_it) | |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
template<meta::different_from< dictionary > other_range_t> requires (std::ranges::input_range<other_range_t>) | |
dictionary (other_range_t &&range) | |
Construct from a different range. | |
template<typename... value_type_> requires ((meta::different_from<dictionary, value_type_> && ...) && (meta::different_from<iterator, value_type_> && ...) && (meta::different_from<const_iterator, value_type_> && ...) && (std::convertible_to<value_type_, value_type> && ...) && (sizeof...(value_type_) > 0)) | |
void | assign (value_type_ &&... args) |
Assign from multiple elements. | |
template<std::ranges::input_range other_range_t> requires std::convertible_to<std::ranges::range_reference_t<other_range_t>, value_type> | |
void | assign (other_range_t &&range) |
Assign from a different range. | |
template<meta::different_from< iterator > begin_it_type, typename end_it_type > requires (meta::different_from<const_iterator, begin_it_type> && std::forward_iterator<begin_it_type> && std::sentinel_for<end_it_type, begin_it_type> && std::convertible_to<std::iter_reference_t<begin_it_type>, value_type>) | |
void | assign (begin_it_type begin_it, end_it_type end_it) |
Assign from pair of iterators. | |
void | assign (iterator begin_it, iterator end_it) |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
void | assign (const_iterator begin_it, const_iterator end_it) |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
Iterators | |
iterator | begin () noexcept |
Returns the begin iterator. | |
const_iterator | begin () const noexcept |
Returns the begin iterator. | |
const_iterator | cbegin () const noexcept |
Returns the begin iterator. | |
iterator | end () noexcept |
Returns iterator past the end. | |
const_iterator | end () const noexcept |
Returns iterator past the end. | |
const_iterator | cend () const noexcept |
Returns iterator past the end. | |
Element access | |
reference | at (size_type const i) |
Return the i-th element. | |
const_reference | at (size_type const i) const |
Return the i-th element. | |
reference | operator[] (size_type const i) noexcept |
Return the i-th element. | |
const_reference | operator[] (size_type const i) const noexcept |
Return the i-th element. | |
reference | front () noexcept |
Return the first element. Calling front on an empty container is undefined. | |
const_reference | front () const noexcept |
Return the first element. Calling front on an empty container is undefined. | |
reference | back () noexcept |
Return the last element. | |
const_reference | back () const noexcept |
Return the last element. | |
Capacity | |
bool | empty () const noexcept |
Checks whether the container is empty. | |
size_type | size () const noexcept |
Returns the number of elements in the container. | |
size_type | max_size () const noexcept |
Returns the maximum number of elements the container is able to hold. | |
size_type | capacity () const noexcept |
Returns the number of elements that the container is able to hold without reallocating (see below). | |
void | reserve (size_type const new_cap) |
Reserve storage in the underlying data types to accomodate for future inserts. | |
void | shrink_to_fit () |
Reduce capacity to current size() to free unused memory. | |
Modifiers | |
void | clear () noexcept |
Removes all elements from the container. | |
template<std::convertible_to< value_type > value_type_ = value_type> | |
void | push_back (value_type_ &&value) |
Appends the given element value to the end of the container. | |
void | emplace_back (auto &&... args) |
Constructs an element in-place at the end of the container. | |
void | pop_back () |
Removes the last element of the container. | |
value_type | extract_back () |
Removes and returns the last element of the container. | |
Friends | |
Comparison operators | |
bool | operator== (dictionary const &lhs, dictionary const &rhs) noexcept |
Performs element-wise comparison. | |
bool | operator<=> (dictionary const &lhs, dictionary const &rhs) noexcept |
Performs element-wise comparison. | |
Key-based element access | |
using | het_key_t = key_t const & |
Type used for key-based access. | |
bool | contains (het_key_t key) const |
Check whether the container has an element with the given key. | |
size_t | count (het_key_t key) const |
The number of elements in the container with the specified key. | |
iterator | find (het_key_t key) |
Find an element with the given key. | |
const_iterator | find (het_key_t key) const |
Find an element with the given key. | |
mapped_ref_t | at (het_key_t key) |
Access element by key. | |
mapped_t const & | at (het_key_t key) const |
Access element by key. | |
mapped_ref_t | operator[] (het_key_t key) |
Access element by key. | |
mapped_t const & | operator[] (het_key_t key) const |
Access element by key. | |
Key-based element access (context-aware) | |
template<small_string key> requires (requires(dictionary d) { get<key>(d); }) | |
decltype(auto) | at (meta::vtag_t< key > key_tag) |
Access element by compile-time string and implicitly call get() on it. | |
template<small_string key> requires (requires(dictionary const d) { get<key>(d); }) | |
decltype(auto) | at (meta::vtag_t< key > key_tag) const |
Access element by compile-time string and implicitly call get() on it. | |
template<small_string key> requires (requires(dictionary d) { get<key>(d); }) | |
decltype(auto) | operator[] (meta::vtag_t< key > key_tag) |
Access element by compile-time string and implicitly call get() on it. | |
template<small_string key> requires (requires(dictionary const d) { get<key>(d); }) | |
decltype(auto) | operator[] (meta::vtag_t< key > key_tag) const |
Access element by compile-time string and implicitly call get() on it. | |
template<small_string key> requires (mapped_t_is_context_aware && requires { get<key>(get<1>(dict.storage[0])); }) | |
decltype(auto) | get (meta::decays_to< dictionary > auto &&dict) |
Access element by compile-time string and implicitly call get() on it. | |
An associative container with contiguous, predictable storage.
key_t | The key type; must be convertible to std::string_view (e.g. also std::string). |
mapped_t | The mapped type; must be an object type. |
mapped_t_is_context_aware | See below. |
This container behaves like a mixture of std::vector and std::unordered_map.
It has the following properties:
std::tuple<key_t, mapped_t>
, but the reference type is std::tuple<key_t const &, mapped_t &>
.operator[size_t]
and ~O(1) push_back (like std::vector).insert()
member, only assign() and push_back() to add elements.erase()
member, only clear() and pop_back() to remove elements.resize()
member, but there is a reserve() member.This data structure is used in several places where the order of elements must be preserved but fast random access by key is still desirable. It usually makes sense when the key-string is short (less than 16 characters), the value_type is large, and the data structure does not need many changes after construction.
The element type (value_type) of the dictionary is std::tuple<key_t, mapped_t>
. Most functions that provide access to the elements, return std::tuple<key_t const &, mapped_t &>
(and not std::tuple<key_t &, mapped_t &>
or std::tuple<key_t, mapped_t> &
). This prevents changes to the key of an element (which would break the container).
Functions that access an element by key, return a reference to the mapped value instead (like for std::unordered_map).
If the template parameter mapped_t_is_context_aware
is set to true, the reference type of the dictionary becomes std::tuple<key_t const &, mapped_t const &>
, i.e. the mapped value in dictionary elements cannot be changed via regular element access.
Additionally, given an object o
of type mapped_t
, if get<"foo">(o)
is valid, this container provides a special interface:
get<"foo">(dict)
friend function that calls get<"foo">(dict.at("foo"))
..at("foo"_vtag)
and operator["foo"_vtag]
member functions with identical semantics.In combination with element types that are derived from std::variant (and additionally provide the aforementioned string-based get-interface), this can be used to create heterogeneous dictionaries, i.e. transparent access to mapped values of different types by string-IDs known at compile-time.
using bio::ranges::dictionary< key_t, mapped_t, mapped_t_is_context_aware >::iterator = std::conditional_t<mapped_t_is_context_aware, const_iterator, detail::random_access_iterator<dictionary> > |
The iterator type.
|
inlineexplicit |
Construct from a list of values of value_type.
value_type_ | A parameter pack where each type is equal to value_type. |
[in] | args | The values to construct from. |
Linear in the number of elements.
Basic exception gurantee.
|
inline |
Construct from two iterators.
begin_it_type | Must model std::forward_iterator and value_type must be constructible from the reference type of begin_it_type. |
end_it_type | Must satisfy std::sentinel_for. |
[in] | begin_it | Begin of range to construct/assign from. |
[in] | end_it | End of range to construct/assign from. |
Linear in the distance between begin_it
and end_it
.
Basic exception gurantee.
|
inlineexplicit |
Construct from a different range.
other_range_t | The type of range to be inserted; must satisfy std::ranges::input_range and value_type must be constructible from std::ranges::range_reference_t<other_range_t>. |
[in] | range | The sequences to construct/assign from. |
Linear in the size of range
.
Basic exception gurantee.
|
inline |
Assign from pair of iterators.
begin_it_type | Must satisfy std::forward_iterator and the value_type must be constructible from the reference type of begin_it_type. |
end_it_type | Must satisfy std::sentinel_for. |
[in] | begin_it | Begin of range to construct/assign from. |
[in] | end_it | End of range to construct/assign from. |
Linear in the distance between begin_it
and end_it
.
Basic exception gurantee.
|
inline |
Assign from a different range.
other_range_t | The type of range to be inserted; must satisfy std::ranges::input_range and value_type must be constructible from std::ranges::range_reference_t<other_range_t>. |
[in] | range | The sequences to construct/assign from. |
Linear in the size of range
.
Basic exception gurantee.
|
inline |
Assign from multiple elements.
[in] | args | Multiple elements of value_type; must be at least one. |
This replaces the container's contents with the provided elements.
Linear in the size of args
and/or container size.
Basic exception gurantee.
|
inline |
Access element by key.
[in] | key | The key to lookup. |
std::out_of_range | if no element is associated with the key. |
Note that this function returns a reference to the mapped object (not a key-value-pair).
Amortized constant.
Basic exception guarantee.
|
inline |
Access element by key.
[in] | key | The key to lookup. |
std::out_of_range | if no element is associated with the key. |
Note that this function returns a reference to the mapped object (not a key-value-pair).
Amortized constant.
Basic exception guarantee.
|
inline |
Access element by compile-time string and implicitly call get() on it.
key | The key to lookup. |
[in] | key_tag | A tag object wrapping the compile-time string. |
get<key>(dict[key])
std::out_of_range | if no element is associated with the key. |
This function is only available if mapped_t_is_context_aware
is set to true and if get<key>()
can be called on an object of type mapped_t
.
Note that while dict[key]
always returns a const &
for context-aware dictionaries, this function may return a writable &
.
Amortized constant.
Basic exception guarantee.
|
inline |
Access element by compile-time string and implicitly call get() on it.
key | The key to lookup. |
[in] | key_tag | A tag object wrapping the compile-time string. |
get<key>(dict[key])
std::out_of_range | if no element is associated with the key. |
This function is only available if mapped_t_is_context_aware
is set to true and if get<key>()
can be called on an object of type mapped_t
.
Note that while dict[key]
always returns a const &
for context-aware dictionaries, this function may return a writable &
.
Amortized constant.
Basic exception guarantee.
|
inline |
Return the i-th element.
[in] | i | Index of the element to retrieve. |
std::out_of_range | If you access an element behind the last. |
i
.Note that this function returns the value_type, i.e. a key-value-pair.
Constant.
Throws std::out_of_range if i >= size()
.
|
inline |
Return the i-th element.
[in] | i | Index of the element to retrieve. |
std::out_of_range | If you access an element behind the last. |
i
.Note that this function returns the value_type, i.e. a key-value-pair.
Constant.
Throws std::out_of_range if i >= size()
.
|
inlinenoexcept |
Return the last element.
Note that this function returns a key-value-pair (not the mapped value).
Calling back on an empty container is undefined. In debug mode an assertion checks the size of the container.
Constant.
No-throw guarantee.
|
inlinenoexcept |
Return the last element.
Note that this function returns a key-value-pair (not the mapped value).
Calling back on an empty container is undefined. In debug mode an assertion checks the size of the container.
Constant.
No-throw guarantee.
|
inlinenoexcept |
Returns the begin iterator.
|
inlinenoexcept |
Returns the number of elements that the container is able to hold without reallocating (see below).
This returns the capacity of the internal storage vector. Depending on the implementation, this may or may not be identical to the capacity of the internal hash-map. Thus, push_back() and emplace_back() within the current capacity are guaranteed to not invalidate any iterators, but may result in the hash-table allocating.
Constant.
No-throw guarantee.
|
inlinenoexcept |
Returns the begin iterator.
|
inlinenoexcept |
Returns iterator past the end.
|
inlinenoexcept |
Removes all elements from the container.
Constant.
No-throw guarantee.
|
inline |
Check whether the container has an element with the given key.
[in] | key | The key to lookup. |
true
if an element with the key exists, false
otherwise.Amortized constant.
No-throw guarantee.
|
inline |
The number of elements in the container with the specified key.
[in] | key | The key to lookup. |
1
if an element with the key exists, 0
otherwise.Since keys are required to be unique, this function can only return 0
or 1
.
Amortized constant.
No-throw guarantee.
|
inline |
Constructs an element in-place at the end of the container.
args | Arguments used to construct the element. |
std::runtime_error | If an element with the key already exists in the container. |
Constant.
Basic exception guarantee.
|
inlinenoexcept |
Checks whether the container is empty.
true
if the container is empty, false
otherwise.Constant.
No-throw guarantee.
|
inlinenoexcept |
Returns iterator past the end.
|
inline |
Removes and returns the last element of the container.
Calling extract_back() on an empty container is undefined. In debug mode an assertion will be thrown.
No iterators or references except for back() and end() are invalidated.
Constant.
Basic exception guarantee.
|
inline |
Find an element with the given key.
[in] | key | The key to lookup. |
Amortized constant.
No-throw guarantee.
|
inline |
Find an element with the given key.
[in] | key | The key to lookup. |
Amortized constant.
No-throw guarantee.
|
inlinenoexcept |
Return the first element. Calling front on an empty container is undefined.
Note that this function returns a key-value-pair (not the mapped value).
Calling front on an empty container is undefined. In debug mode an assertion checks the size of the container.
Constant.
No-throw guarantee.
|
inlinenoexcept |
Return the first element. Calling front on an empty container is undefined.
Note that this function returns a key-value-pair (not the mapped value).
Calling front on an empty container is undefined. In debug mode an assertion checks the size of the container.
Constant.
No-throw guarantee.
|
inlinenoexcept |
Returns the maximum number of elements the container is able to hold.
This value typically reflects the theoretical limit on the size of the container. At runtime, the size of the container may be limited to a value smaller than max_size() by the amount of RAM available.
Constant.
No-throw guarantee.
|
inline |
Access element by key.
[in] | key | The key to lookup. |
std::out_of_range | if no element is associated with the key. |
This function is identical to .at(key)
. It never inserts elements like the respective function in std::unordered_map would do; instead it throws an exception if an element with the given key does not exist.
Amortized constant.
Basic exception guarantee.
|
inline |
Access element by key.
[in] | key | The key to lookup. |
std::out_of_range | if no element is associated with the key. |
This function is identical to .at(key)
. It never inserts elements like the respective function in std::unordered_map would do; instead it throws an exception if an element with the given key does not exist.
Amortized constant.
Basic exception guarantee.
|
inline |
Access element by compile-time string and implicitly call get() on it.
key | The key to lookup. |
[in] | key_tag | A tag object wrapping the compile-time string. |
get<key>(dict[key])
std::out_of_range | if no element is associated with the key. |
This function is only available if mapped_t_is_context_aware
is set to true and if get<key>()
can be called on an object of type mapped_t
.
Note that while dict[key]
always returns a const &
for context-aware dictionaries, this function may return a writable &
.
Amortized constant.
Basic exception guarantee.
|
inline |
Access element by compile-time string and implicitly call get() on it.
key | The key to lookup. |
[in] | key_tag | A tag object wrapping the compile-time string. |
get<key>(dict[key])
std::out_of_range | if no element is associated with the key. |
This function is only available if mapped_t_is_context_aware
is set to true and if get<key>()
can be called on an object of type mapped_t
.
Note that while dict[key]
always returns a const &
for context-aware dictionaries, this function may return a writable &
.
Amortized constant.
Basic exception guarantee.
|
inlinenoexcept |
Return the i-th element.
i | The element to retrieve. |
i
.Note that this function returns a key-value-pair (not the mapped value).
Accessing an element behind the last causes undefined behaviour. In debug mode an assertion checks the size of the container.
Constant.
No-throw guarantee.
|
inlinenoexcept |
Return the i-th element.
i | The element to retrieve. |
i
.Note that this function returns a key-value-pair (not the mapped value).
Accessing an element behind the last causes undefined behaviour. In debug mode an assertion checks the size of the container.
Constant.
No-throw guarantee.
|
inline |
Removes the last element of the container.
Calling pop_back() on an empty container is undefined. In debug mode an assertion will be thrown.
No iterators or references except for back() and end() are invalidated.
Constant.
No-throw guarantee.
|
inline |
Appends the given element value to the end of the container.
value | The value to append. |
std::runtime_error | If an element with the key already exists in the container. |
Constant.
Strong exception guarantee.
|
inline |
Reserve storage in the underlying data types to accomodate for future inserts.
[in] | new_cap | The desired capacity. |
This reserves the specified capacity in both internal data structures to prevent reallocation on subsequent back insertions. It never reduces the capacity(); use shrink_to_fit() for that.
Average case: linear in new_cap. Worst case: quadratic in new_cap.
Basic exception guarantee.
|
inline |
|
inlinenoexcept |
Returns the number of elements in the container.
Constant.
No-throw guarantee.
|
friend |
Access element by compile-time string and implicitly call get() on it.
key | The key to lookup. |
[in,out] | dict | An object of this type. |
get<key>(dict[key])
std::out_of_range | if no element is associated with the key. |
This function is only available if mapped_t_is_context_aware
is set to true and if get<key>()
can be called on an object of type mapped_t
.
Note that while dict[key]
always returns a const &
for context-aware dictionaries, this function may return a writable &
.
Amortized constant.
Basic exception guarantee.