A wrapper for STL containers such as tuple, pair, and array. These containers force the programmer to remember the function/meaning of each element based on its position. This is error-prone. To mitigate this, the named wrapper allows to assign a name, via a template parameters, to each element so that subsequently it can be used to query elements by name, and to ensure that the assignment takes in account the order of the elements. More...
#include <tuple>#include "concepts/util.h"#include "util/constfor.h"#include "util/string_literal.h"#include "named_util.h"Go to the source code of this file.
Classes | |
| struct | named< T, NAMES > |
| named container More... | |
| struct | is_named< T > |
| struct | is_named< named< T, NAMES... > > |
| struct | named_equivalence< U, V > |
| struct | named_equivalence< U, V > |
| struct | tuple_size< bbm::named< T, NAMES... > > |
| tuple_size specialization (to support structured binding) More... | |
| struct | tuple_element< idx, bbm::named< T, NAMES... > > |
| tuple_element specialization (to support structured binding) More... | |
Namespaces | |
| namespace | bbm |
| namespace | std |
Functions | |
| template<string_literal... NAMES, typename T > requires (sizeof...(NAMES) == 0) || (concepts::gettable<T> && (sizeof...(NAMES) == std::tuple_size_v<std::decay_t<T>>)) | |
| constexpr named< anonymize_t< T >, NAMES... > | make_named (T &&t) |
| Make a named of a gettable type (with size == #NAMES); renames if the type is a named container. | |
| template<string_literal... NAMES, typename... Ts> requires (sizeof...(NAMES) == sizeof...(Ts)) | |
| constexpr auto | make_named (Ts &&... ts) |
| Make a named tuple from a list of arguments (number of arguments == #NAMES) | |
| template<string_literal... NAMES, typename T > requires is_named_v<T> | |
| constexpr auto | pick (T &&t) |
| Pick a subset/reshuffle a named container T and return as a named tuple. | |
| template<string_literal... NAMES, typename... Ts> requires (sizeof...(NAMES) == sizeof...(Ts)) | |
| named< std::tuple< Ts &... >, NAMES... > | tie (Ts &&... src) |
| Tie by name. | |
Get by name | |
| template<string_literal NAME, string_literal... SUBNAME, typename T > requires is_named_v<T> | |
| constexpr decltype(auto) | get (T &&src) |
| template<string_literal NAME, string_literal... SUBNAME, typename T > requires is_named_v<T> | |
| constexpr decltype(auto) | get (const T &src) |
Variables | |
type traits | |
@{ | |
| template<typename T > | |
| constexpr bool | is_named_v = is_named<std::decay_t<T>>::value |
named_equivalence trait: do two types have the same set of names? | |
| template<typename U , typename V > | |
| static constexpr bool | named_equivalence_v = named_equivalence<U,V>::value |
anonymize trait: remove the names | |
| template<typename T > | |
| using | anonymize_t = std::decay_t< decltype(anonymize_v(std::declval< T >()))> |
| template<typename T > | |
| constexpr decltype(auto) | anonymize_v (T &&t) |
A wrapper for STL containers such as tuple, pair, and array. These containers force the programmer to remember the function/meaning of each element based on its position. This is error-prone. To mitigate this, the named wrapper allows to assign a name, via a template parameters, to each element so that subsequently it can be used to query elements by name, and to ensure that the assignment takes in account the order of the elements.
named container elements vs structs** A struct cannot be defined in a function signature, and thus requires an external struct definition. This is cumbersome for single use structures. Structured bindings introduced in C++17 do not completely solve this problem, since the definition is still annonymous. Example:
Alternatively, a single use tuple can be used:
but now the meaning of each element is implicit (is 'a' the first or second float?). Named containers provide an alternative:
Equivallent correspondling look ups for the above 3 stratgies are:
While a bit more verbose, named containers are more closely related to structs, and thus less error prone.
Addtionally, named containers also allow for 'tie' with names:
The following will also take the order of names in account:
Similarly there are 2 helper methods for making a named structure:
To pick a subset of named elements use:
All of this can be combined with structured bindings:
The former has the preference, since it allows to:
Named structures can also be recursive; a shortcut for get allows to directly query the recursive values:
Note: a recusive named type wraps the inner named type in a tuple. Without wrapping, the names of the inner type are overwritten: