4.4.0
|
|
Freundlich's C++ toolkit |
A record class that holds named elements in a generic way.
A set of name-type pairs, for example { age : int, name : string }
, is generally called a record. In C++, these are usually declared using classes or structs:
The shortcoming is that such a struct provides no generic structure. Imagine you would like to write a generic function that prints such a struct, given you already know how to print ints and strings. A concrete implementation would look like this:
This, however, only works for the concrete type person
. To find a more abstract representation, we need to specify which elements a struct has in a generic way. To this end, we first of all need to create unique types that represent element names which we call labels. Such a label together with a unique tag type is created by FCPPT_RECORD_MAKE_LABEL:
A record element is represented by fcppt::record::element. It gets a label together with a type as its template parameters:
Finally, a record object consists of a list of elements:
Before we continue, here is a small example of how to use such a record:
The initialization syntax is further explained in Initialization. The functions fcppt::record::get and fcppt::record::set are used to read and write elements.
To return to our goal of creating a generic output function, we first create a function print_label
that given a record and a label prints the element for the given label to a stream:
The function fcppt::record::element_vector returns an fcppt::mpl::list::object of the elements of a record. Such a list can be used by fcppt::algorithm::loop, which will call a function for every type in the sequence. We use this to call print_label
for every element of the record:
Now, if we were to add another member to the person record, say address
, we wouldn't have to change our print
function.
There are two ways to initialize a record: First, we can initialize every element separately. This is done by the special syntax
Here, it is important that all labels of the record appear exactly once. Also, the types of the values have to match the types of the record.
The second way to initialize a record is via the fcppt::record::init function. It is a generic function that calls a function for every element of the record (from first to last), which can be used to initialize a record in a generic way. Assume that we have the values for our record in a stream:
We then read the corresponding elements of the record from the stream:
The lambda is first called for age_element
and second for name_element
because of the order they appear in the declaration. So, in the example, age
will be 42
and name
will be "test"
.
Unlike normal labels, there are also labels that take an additional argument. Consider a sprite that can have a fixed number of textures t_1,...,t_n
which will be rendered in order. To create a label that is parameterized, we use FCPPT_RECORD_MAKE_LABEL_ARG:
Next, we create a type function that takes an unsigned integer I
to the I
'th texture element:
Finally, to declare our sprite with N textures, we use a std::integer_sequence
to create a record with types sprite_element<0>, ..., sprite_element<N-1>
.
Here is an example that shows how such a sprite can be initialized:
Header file | Description |
---|---|
object_fwd.hpp | Contains fcppt::record::object record's declaration. |
object_decl.hpp | Contains fcppt::record::object record's definition. |
object_impl.hpp | Contains the definition of fcppt::record::object record's member functions. |
object.hpp | Includes object_impl.hpp and comparison.hpp . |
comparison.hpp | Contains operator== and operator!= . |
element_fwd.hpp | Contains fcppt::record::element element's declaration. |
element.hpp | Contains fcppt::record::element element's definition. |
element_to_label.hpp | Contains fcppt::record::element_to_label. |
element_to_type.hpp | Contains fcppt::record::element_to_type. |
from_list_fwd.hpp | Contains fcppt::record::from_list. |
from_list.hpp | Includes fcppt/record/from_list_fwd.hpp and defines fcppt::record::object. |
get.hpp | Contains fcppt::record::get. |
init.hpp | Contains fcppt::record::init. |
label_fwd.hpp | Contains fcppt::record::label label's declaration. |
label_decl.hpp | Contains fcppt::record::label label's definition. |
label_impl.hpp | Contains the definition of fcppt::record::label label's member functions. |
label.hpp | Includes label_impl.hpp . |
label_name.hpp | Contains fcppt::record::label_name. |
label_value_type.hpp | Contains fcppt::record::label_value_type. |
make_label_fwd.hpp | Contains FCPPT_RECORD_MAKE_LABEL and includes label_fwd.hpp . |
make_label.hpp | Includes make_label_fwd.hpp and label_impl.hpp . |
make_label_arg_fwd.hpp | Contains FCPPT_RECORD_MAKE_LABEL_ARG and includes label_fwd.hpp . |
make_label_arg.hpp | Includes make_label_arg_fwd.hpp and label_impl.hpp . |
output.hpp | Contains operator<< . |
set.hpp | Contains fcppt::record::set. |
Classes | |
struct | fcppt::record::element< Label, Type > |
An element of a record. More... | |
class | fcppt::record::element_init< Tag, Type > |
The type produced by initializing a single record element. More... | |
struct | fcppt::record::is_element< typename > |
Tests if a type is an fcppt::record::element. More... | |
struct | fcppt::record::is_label< typename > |
Tests if a type is an fcppt::record::label. More... | |
struct | fcppt::record::is_object< T > |
Tests if a type is an fcppt::record::object. More... | |
struct | fcppt::record::label< Tag > |
A type identifying an element of a record. More... | |
class | fcppt::record::object< Elements > |
A generic struct that identifies elements by types. More... | |
Macros | |
#define | FCPPT_RECORD_MAKE_LABEL_ARG(name, arg) |
Creates a parametrized fcppt::record::label. | |
#define | FCPPT_RECORD_MAKE_LABEL(name) |
Creates an fcppt::record::label. | |
Typedefs | |
template<fcppt::mpl::list::object_concept List> | |
using | fcppt::mpl::list::unique = fcppt::mpl::set::to_list< fcppt::mpl::set::from_list_relaxed< List > > |
Removes duplicates from a list. | |
template<fcppt::mpl::list::object_concept Records> | |
using | fcppt::record::all_disjoint = std::is_same< fcppt::mpl::set::size< fcppt::mpl::list::fold< Records, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::mpl::set::union_ >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::label_set >, fcppt::mpl::arg< 1 > >, fcppt::mpl::arg< 2 > >, fcppt::mpl::set::object<> > >, fcppt::mpl::list::size< fcppt::mpl::list::join< fcppt::mpl::list::map< Records, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::mpl::set::to_list >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::label_set >, fcppt::mpl::arg< 1 > > > > > > > |
Tests if multiple records have disjoint label sets. | |
template<typename RecordL , typename RecordR > | |
using | fcppt::record::are_disjoint = std::is_same< fcppt::mpl::set::intersection< fcppt::record::label_set< RecordL >, fcppt::record::label_set< RecordR > >, fcppt::mpl::set::object<> > |
Tests if two records have disjoint label sets. | |
template<typename Record1 , typename Record2 > | |
using | fcppt::record::are_equivalent = fcppt::mpl::map::equal< fcppt::record::element_map< Record1 >, fcppt::record::element_map< Record2 > > |
Tests if two records have the same element maps. | |
template<typename RecordL , typename RecordR > | |
using | fcppt::record::disjoint_product = typename fcppt::record::detail::disjoint_product< RecordL, RecordR >::type |
The product of two disjoint records. | |
template<typename Type > | |
using | fcppt::record::element_init_tag = typename fcppt::record::detail::element_init_tag< Type >::type |
The tag type of fcppt::record::element_init. | |
template<typename Type > | |
using | fcppt::record::element_init_type = typename fcppt::record::detail::element_init_type< Type >::type |
The value type of fcppt::record::element_init. | |
template<typename Record > | |
using | fcppt::record::element_map = fcppt::mpl::list::fold< fcppt::record::element_vector< Record >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::mpl::map::insert >, fcppt::mpl::arg< 2 >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::element_to_label >, fcppt::mpl::arg< 1 > >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::element_to_type >, fcppt::mpl::arg< 1 > > >, fcppt::mpl::map::object<> > |
A metafunction computing the element map of a record. | |
template<typename Record > | |
using | fcppt::record::element_tag_tuple = fcppt::mpl::list::as_tuple< fcppt::mpl::list::map< fcppt::record::element_vector< Record >, fcppt::mpl::lambda< fcppt::tag > > > |
A metafunction returning the elements of record as a fcppt::tuple::object of fcppt::tag types. | |
template<typename Element > | |
using | fcppt::record::element_to_label = typename fcppt::record::detail::element_to_label< Element >::type |
Extracts the type of an fcppt::record::element. | |
template<typename Element > | |
using | fcppt::record::element_to_type = typename fcppt::record::detail::element_to_type< std::remove_cv_t< Element > >::type |
Extracts the label of an element. | |
template<typename Record > | |
using | fcppt::record::element_vector = typename fcppt::record::detail::element_vector< Record >::type |
A metafunction returning the elements of record as an MPL vector. | |
template<typename... Args> | |
using | fcppt::record::enable_vararg_ctor = std::enable_if_t< std::conjunction_v< fcppt::record::detail::is_element_init< std::remove_cvref_t< Args > >... > > |
Checks if a parameter pack is suitable for record initialization. | |
template<fcppt::mpl::list::object_concept List> | |
using | fcppt::record::from_list = fcppt::mpl::list::as< fcppt::record::object, List > |
Declares a record using an mpl::list. | |
template<typename Record , typename Label > | |
using | fcppt::record::has_label = fcppt::mpl::set::contains< fcppt::record::label_set< Record >, Label > |
Tests if a record has an fcppt::record::label. | |
template<typename Record > | |
using | fcppt::record::label_set = fcppt::mpl::set::from_list_relaxed< fcppt::record::detail::label_list< fcppt::record::element_vector< Record > > > |
The set of labels of a record. | |
template<typename Record , typename Label > | |
using | fcppt::record::label_value_type = fcppt::record::element_to_type< fcppt::record::detail::find_element< fcppt::record::element_vector< Record >, Label > > |
Metafunction that computes the value type of a label inside a record. | |
template<typename Record , typename Function > | |
using | fcppt::record::map_elements = fcppt::record::from_list< fcppt::mpl::list::map< fcppt::record::element_vector< Record >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::element >, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::element_to_label >, fcppt::mpl::arg< 1 > >, Function > > > |
Maps the elements of a vector using a metafunction. | |
template<typename Record , typename Function > | |
using | fcppt::record::map_result = fcppt::record::map_elements< Record, fcppt::mpl::bind< fcppt::mpl::lambda< fcppt::record::detail::map_result >, fcppt::mpl::constant< Function >, fcppt::mpl::arg< 1 > > > |
The result of mapping a record. | |
Functions | |
template<typename... Types1, typename... Types2> | |
bool | fcppt::record::operator== (fcppt::record::object< Types1... > const &_record1, fcppt::record::object< Types2... > const &_record2) |
Compares two records for equality. | |
template<typename... Types1, typename... Types2> | |
bool | fcppt::record::operator!= (fcppt::record::object< Types1... > const &_record1, fcppt::record::object< Types2... > const &_record2) |
Compares two records for inequality. | |
template<typename Label , typename... Elements> | |
fcppt::record::label_value_type< fcppt::record::object< Elements... >, Label > const & | fcppt::record::get (fcppt::record::object< Elements... > const &_arg) |
Gets an element from a record. | |
template<typename Label , typename... Elements> | |
fcppt::record::label_value_type< fcppt::record::object< Elements... >, Label > & | fcppt::record::get (fcppt::record::object< Elements... > &_arg) |
Gets an element from a record. | |
template<typename Result , typename Function > | |
Result | fcppt::record::init (Function const &_function) |
Initializes a record using a function. | |
template<typename Label > | |
std::string | fcppt::record::label_name () |
Returns the name of a label as a string. | |
template<typename... Args, typename = fcppt::record::enable_vararg_ctor<Args...>> requires (fcppt::mpl::list::distinct< fcppt::mpl::list::object<fcppt::record::label<fcppt::record::element_init_tag<Args>>...>>::value) | |
fcppt::record::object< fcppt::record::element< fcppt::record::label< fcppt::record::element_init_tag< Args > >, fcppt::record::element_init_type< Args > >... > | fcppt::record::make (Args &&..._args) |
Creates a record from an initializer list. | |
template<typename Record , typename Function > | |
fcppt::record::map_result< Record, Function > | fcppt::record::map (Record &&_record, Function const &_function) |
Maps a record using a function. | |
template<typename Record1 , typename Record2 > | |
fcppt::record::disjoint_product< std::remove_cvref_t< Record1 >, std::remove_cvref_t< Record2 > > | fcppt::record::multiply_disjoint (Record1 &&_record1, Record2 &&_record2) |
Creates the disjoint product of two records. | |
template<typename Ch , typename Traits , typename... Elements> | |
std::basic_ostream< Ch, Traits > & | fcppt::record::operator<< (std::basic_ostream< Ch, Traits > &_stream, fcppt::record::object< Elements... > const &_record) |
Outputs a record to a stream. | |
template<typename Result , typename Arg > | |
Result | fcppt::record::permute (Arg &&_arg) |
Permutes one record into another. | |
template<typename Label , typename... Elements> | |
void | fcppt::record::set (fcppt::record::object< Elements... > &_arg, fcppt::record::label_value_type< fcppt::record::object< Elements... >, Label > const &_value) |
Sets an element in a record by copy. | |
template<typename Label , typename... Elements> | |
void | fcppt::record::set (fcppt::record::object< Elements... > &_arg, fcppt::record::label_value_type< fcppt::record::object< Elements... >, Label > &&_value) |
Sets an element in a record by move. | |
#define FCPPT_RECORD_MAKE_LABEL | ( | name | ) |
Creates an fcppt::record::label.
Creates an fcppt::record::label, passing it a unique, implementation-defined tag type.
name | The name of the label type. |
#define FCPPT_RECORD_MAKE_LABEL_ARG | ( | name, | |
arg | |||
) |
Creates a parametrized fcppt::record::label.
Creates an fcppt::record::label, passing it a unique, implementation-defined tag type that depends on a template parameter. The result is a template alias that still takes a parameter of type arg.
name | The name of the label type. |
arg | The type of the template parameter. |
using fcppt::record::all_disjoint = typedef std::is_same< fcppt::mpl::set::size<fcppt::mpl::list::fold< Records, fcppt::mpl::bind< fcppt::mpl::lambda<fcppt::mpl::set::union_>, fcppt::mpl::bind<fcppt::mpl::lambda<fcppt::record::label_set>, fcppt::mpl::arg<1> >, fcppt::mpl::arg<2> >, fcppt::mpl::set::object<> >>, fcppt::mpl::list::size<fcppt::mpl::list::join<fcppt::mpl::list::map< Records, fcppt::mpl::bind< fcppt::mpl::lambda<fcppt::mpl::set::to_list>, fcppt::mpl::bind<fcppt::mpl::lambda<fcppt::record::label_set>, fcppt::mpl::arg<1> >> >> >> |
Tests if multiple records have disjoint label sets.
using fcppt::record::are_disjoint = typedef std::is_same< fcppt::mpl::set:: intersection<fcppt::record::label_set<RecordL>, fcppt::record::label_set<RecordR> >, fcppt::mpl::set::object<> > |
Tests if two records have disjoint label sets.
using fcppt::record::are_equivalent = typedef fcppt::mpl:: map::equal<fcppt::record::element_map<Record1>, fcppt::record::element_map<Record2> > |
Tests if two records have the same element maps.
using fcppt::record::disjoint_product = typedef typename fcppt::record::detail::disjoint_product<RecordL, RecordR>::type |
The product of two disjoint records.
using fcppt::record::element_init_tag = typedef typename fcppt::record::detail::element_init_tag<Type>::type |
The tag type of fcppt::record::element_init.
using fcppt::record::element_init_type = typedef typename fcppt::record::detail::element_init_type<Type>::type |
The value type of fcppt::record::element_init.
A metafunction computing the element map of a record.
Record | Must be an fcppt::record::object. |
using fcppt::record::element_tag_tuple = typedef fcppt::mpl::list::as_tuple< fcppt::mpl::list::map<fcppt::record::element_vector<Record>, fcppt::mpl::lambda<fcppt::tag> >> |
A metafunction returning the elements of record as a fcppt::tuple::object
of fcppt::tag
types.
Record | Must be an fcppt::record::object. |
using fcppt::record::element_to_label = typedef typename fcppt::record::detail::element_to_label<Element>::type |
Extracts the type of an fcppt::record::element.
Element | Must be an fcppt::record::element. |
using fcppt::record::element_to_type = typedef typename fcppt::record::detail::element_to_type<std::remove_cv_t<Element> >::type |
Extracts the label of an element.
Element | Must be an fcppt::record::element. |
using fcppt::record::element_vector = typedef typename fcppt::record::detail::element_vector<Record>::type |
A metafunction returning the elements of record as an MPL vector.
Record | Must be an fcppt::record::object. |
using fcppt::record::enable_vararg_ctor = typedef std::enable_if_t<std::conjunction_v< fcppt::record::detail::is_element_init<std::remove_cvref_t<Args> >...> > |
Checks if a parameter pack is suitable for record initialization.
using fcppt::record::from_list = typedef fcppt::mpl::list::as<fcppt::record::object, List> |
Declares a record using an mpl::list.
using fcppt::record::has_label = typedef fcppt::mpl::set::contains<fcppt::record::label_set<Record>, Label> |
Tests if a record has an fcppt::record::label.
using fcppt::record::label_set = typedef fcppt::mpl::set::from_list_relaxed< fcppt::record::detail::label_list<fcppt::record::element_vector<Record> >> |
The set of labels of a record.
Record | Must be an fcppt::record::object. |
using fcppt::record::label_value_type = typedef fcppt::record::element_to_type< fcppt::record::detail::find_element<fcppt::record::element_vector<Record>, Label> > |
Metafunction that computes the value type of a label inside a record.
Returns the type the label Label has in Record.
using fcppt::record::map_elements = typedef fcppt::record::from_list<fcppt::mpl::list::map< fcppt::record::element_vector<Record>, fcppt::mpl::bind< fcppt::mpl::lambda<fcppt::record::element>, fcppt::mpl::bind<fcppt::mpl::lambda<fcppt::record::element_to_label>, fcppt::mpl::arg<1> >, Function> >> |
Maps the elements of a vector using a metafunction.
Record | Must be an fcppt::record::object. |
Function | A metafunction accepting fcppt::record::element as parameter and returning the new mapped type. |
using fcppt::record::map_result = typedef fcppt::record::map_elements< Record, fcppt::mpl::bind< fcppt::mpl::lambda<fcppt::record::detail::map_result>, fcppt::mpl::constant<Function>, fcppt::mpl::arg<1> >> |
The result of mapping a record.
using fcppt::mpl::list::unique = typedef fcppt::mpl::set::to_list<fcppt::mpl::set::from_list_relaxed<List> > |
Removes duplicates from a list.
|
inline |
Gets an element from a record.
Returns the element identified by Label from _arg.
|
inline |
Gets an element from a record.
Returns the element identified by Label from _arg.
|
inline |
Initializes a record using a function.
Let element<L_1,T_1>, ..., element<L_n,T_n>
be the elements of Result. _function is then called as (element<L_i,T_i>)
for i = 1,..,n
.
Result | Must be an fcppt::record::object. |
Function | A polymorphic function callable as fcppt::record::label_value_type<Result, L> (fcppt::record::element<L,T>) for every element<L,T> in Result. |
|
inline |
Returns the name of a label as a string.
|
inline |
Creates a record from an initializer list.
Args
must be created using label{} = value
expressions.
|
inline |
Maps a record using a function.
For every fcppt::record::element<L,T>
in Record, _function(get<L>(_record))
is stored in the result type.
Record | An fcppt::record::object. |
Function | a polymorphic function that can be called with every type in Record. |
fcppt::record::disjoint_product< std::remove_cvref_t< Record1 >, std::remove_cvref_t< Record2 > > fcppt::record::multiply_disjoint | ( | Record1 && | _record1, |
Record2 && | _record2 | ||
) |
Creates the disjoint product of two records.
Record1 | Must be an fcppt::record::object that is disjoint from Record2. |
Record2 | Must be an fcppt::record::object that is disjoint from Record1. |
|
inline |
Compares two records for inequality.
Types1 | Must be equivalent to Types2 |
Types2 | Must be equivalent to Types1 |
std::basic_ostream< Ch, Traits > & fcppt::record::operator<< | ( | std::basic_ostream< Ch, Traits > & | _stream, |
fcppt::record::object< Elements... > const & | _record | ||
) |
Outputs a record to a stream.
bool fcppt::record::operator== | ( | fcppt::record::object< Types1... > const & | _record1, |
fcppt::record::object< Types2... > const & | _record2 | ||
) |
Compares two records for equality.
Types1 | Must be equivalent to Types2 |
Types2 | Must be equivalent to Types1 |
|
inline |
Permutes one record into another.
Result | Must be equivalent to Arg, and must be an fcppt::record::object. |
Arg | Must be equivalent to Result, and must be an fcppt::record::object. |
|
inline |
Sets an element in a record by move.
Moves _value to the element identified by Label in _arg.
|
inline |
Sets an element in a record by copy.
Copies _value to the element identified by Label in _arg.