2.6.0
Freundlich's C++ toolkit
Classes | Macros | Typedefs | Functions
fcppt.record

Description

A record class that holds named elements in a generic way.

Motivation

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:

struct person
{
int age;
};

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:

void
std::ostream &_stream,
person const &_person
)
{
_stream
<< "age: " << _person.age
<< ", "
<< "name: " << _person.name;
}

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:

// age = fcppt::record::label<T> for a unique tag type T
age
);
// name = fcppt::record::label<T> for a unique tag type T
);

A record element is represented by fcppt::record::element. It gets a label together with a type as its template parameters:

typedef
age,
int
>
age_element;
typedef
>
name_element;

Finally, a record object consists of an MPL sequence of elements:

typedef
boost::mpl::vector<
age_element,
name_element
>
>
person;

A shorthand, which omits the MPL sequence, is fcppt::record::variadic.

typedef
age_element,
name_element
>
person;

Before we continue, here is a small example of how to use such a record:

person test_person{
age{} = 42,
name{} = std::string("test")
};
std::cout << fcppt::record::get<age>(test_person) << '\n';
fcppt::record::set<age>(test_person, 13);
std::cout << fcppt::record::get<age>(test_person) << '\n';

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:

template<
typename Label,
typename Types
>
void
print_label(
std::ostream &_stream,
Types
> const &_record
)
{
_stream
// extract the label name
<< fcppt::record::label_name<Label>()
<< ": "
// extract the value for the label
<< fcppt::record::get<Label>(_record)
<< ", ";
}

Remember that a record is declared by giving it an MPL sequence of elements. Such an MPL sequence 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:

template<
typename Types
>
void
std::ostream &_stream,
Types
> const &_record
)
{
// Loop over all types in the record
Types{},
[
&_stream,
&_record
](
// _element is fcppt::tag<fcppt::record::element<L,T>>
auto const _element
)
{
// _element is only used for its type
FCPPT_USE(_element);
print_label<
// Extract the label of _element
decltype(_element)
>
>
>(
_stream,
_record
);
}
);
}

Now, if we were to add another member to the person record, say address, we wouldn't have to change our print function.

Initialization

There are two ways to initialize a record: First, we can initialize every element separately. This is done by the special syntax

record{label_1{} = value_1, ..., label_n{} = value_n}

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.

person const test_person{
age{} = 42
// error: forgotten name
};
person const test_person{
// error: age specified twice
age{} = 42,
age{} = 10
};
person const test_person{
age{} = 42,
name{} = 10 // error: wrong type for name
};

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:

"42 test"
};

We then read the corresponding elements of the record from the stream:

person const result{
person
>(
[
&stream
](
// _element is fcppt::record::element<L,T>
auto const _element
)
{
// _element is only used for its type
FCPPT_USE(_element);
// Extract the type of _element
decltype(_element)
> input;
if(
!(stream >> input)
)
throw
std::runtime_error{"failure"};
return
}
)
};

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

Labels with an argument

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 parametrized, we use FCPPT_RECORD_MAKE_LABEL_ARG:

// Parametrize the texture label with an unsigned int.
// template<unsigned I> using texture = fcppt::record::label<T,I> for a unique tag type T
texture,
unsigned
);

Next, we create a type function that takes an unsigned integer I to the I'th texture element:

template<
typename I
>
struct sprite_element
{
typedef
texture<
I::value
>,
>
type;
};

Finally, to declare our sprite with N textures, we use boost::mpl::transform to transform a sequence of integers 0,...,N-1 to sprite_element<0>, ..., sprite_element<N-1>.

template<
unsigned N
>
using
sprite
=
typename
boost::mpl::transform<
// copy is needed because transform does not work on range_c
typename
boost::mpl::range_c<
unsigned,
0u,
N
>
>::type,
sprite_element<
>
>::type
>;

Here is an example that shows how such a sprite can be initialized:

sprite<
2
> const test_sprite{
texture<0>{} = std::string("ground"),
texture<1>{} = std::string("clouds")
};

Header files

Header file Description
object_fwd.hpp Contains record's declaration.
object_decl.hpp Contains record's definition.
object_impl.hpp Contains the definition of record's member functions.
object.hpp Includes object_impl.hpp and comparison.hpp.
comparison.hpp Contains operator== and operator!=.
element_fwd.hpp Contains element's declaration.
element.hpp Contains element's definition.
element_to_label.hpp Contains fcppt::record::element_to_label.
element_to_label_tpl.hpp Contains fcppt::record::element_to_label_tpl.
element_to_type.hpp Contains fcppt::record::element_to_type.
element_to_type_tpl.hpp Contains fcppt::record::element_to_type_tpl.
get.hpp Contains fcppt::record::get.
init.hpp Contains fcppt::record::init.
label_fwd.hpp Contains label's declaration.
label_decl.hpp Contains label's definition.
label_impl.hpp Contains the definition of 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.
variadic_fwd.hpp Contains fcppt::record::variadic and declares fcppt::record::object.
variadic.hpp Includes fcppt/record/object_fwd.hpp and defines fcppt::record::object.

Classes

struct  fcppt::record::element< Label, Type >
 An element of a record. More...
 
struct  fcppt::record::element_map_tpl< Record >
 A metafunction computing the element map of a record. More...
 
struct  fcppt::record::element_to_label_tpl< Element >
 Extracts the type of an element and provides a type typedef to it. More...
 
struct  fcppt::record::element_to_type_tpl< Element >
 Extracts the label of an element and provides a type typedef to it. More...
 
struct  fcppt::record::element_vector_tpl< Record >
 A metafunction returning the elements of record as an MPL vector. More...
 
struct  fcppt::record::has_label< Record, Label >
 Tests if a record has an fcppt::record::label. 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...
 
struct  fcppt::record::label_set_tpl< Record >
 A metafunction computing the set of labels of a record. More...
 
struct  fcppt::record::label_value_type_tpl< Record, Label >
 Metafunction that computes the value type of a label inside a record. More...
 
class  fcppt::record::object< Types >
 A generic struct that identifies elements by types. More...
 

Macros

#define FCPPT_RECORD_MAKE_LABEL_ARG(name, arg)
 Creates a parametrized fcppt::record::label. More...
 
#define FCPPT_RECORD_MAKE_LABEL(name)
 Creates an fcppt::record::label. More...
 

Typedefs

template<typename Record1 , typename Record2 >
using fcppt::record::are_equivalent = boost::mpl::and_< boost::mpl::empty< typename fcppt::mpl::set_symmetric_difference< fcppt::record::label_set< Record1 >, fcppt::record::label_set< Record2 > >::type >, typename fcppt::mpl::all_of< fcppt::record::label_set< Record1 >, std::is_same< boost::mpl::at< fcppt::record::element_map< Record1 >, boost::mpl::_1 >, boost::mpl::at< fcppt::record::element_map< Record2 >, boost::mpl::_1 > > >::type >
 Tests if two records have the same element maps. More...
 
template<typename Record >
using fcppt::record::element_map = typename fcppt::record::element_map_tpl< Record >::type
 The element map of a record. More...
 
template<typename Element >
using fcppt::record::element_to_label = typename fcppt::record::element_to_label_tpl< typename std::decay< Element >::type >::type
 Extracts the type of an element. More...
 
template<typename Element >
using fcppt::record::element_to_type = typename fcppt::record::element_to_type_tpl< typename std::decay< Element >::type >::type
 Extracts the label of an element. More...
 
template<typename Record >
using fcppt::record::element_vector = typename fcppt::record::element_vector_tpl< Record >::type
 The elements of record as an MPL vector. More...
 
template<typename Record >
using fcppt::record::label_set = typename fcppt::record::label_set_tpl< Record >::type
 The set of labels of a record. More...
 
template<typename Record , typename Label >
using fcppt::record::label_value_type = typename fcppt::record::label_value_type_tpl< Record, Label >::type
 The value type of a label inside a record. More...
 
template<typename Record , typename Function >
using fcppt::record::map_elements = fcppt::record::object< typename boost::mpl::transform< fcppt::record::element_vector< Record >, fcppt::record::element< fcppt::record::element_to_label_tpl< boost::mpl::_1 >, boost::mpl::bind< typename boost::mpl::lambda< Function >::type, boost::mpl::_1 > > >::type >
 Maps the elements of a vector using a metafunction. More...
 
template<typename Record , typename Function >
using fcppt::record::map_result = fcppt::record::map_elements< Record, fcppt::record::detail::map_result< Function, boost::mpl::_ > >
 The result of mapping a record. More...
 
template<typename... Types>
using fcppt::record::variadic = fcppt::record::object< boost::mpl::vector< Types... > >
 Declares a record using a parameter pack. More...
 

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. More...
 
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. More...
 
template<typename Label , typename Types >
fcppt::record::label_value_type< fcppt::record::object< Types >, Label > const & fcppt::record::get (fcppt::record::object< Types > const &_arg)
 Gets an element from a record. More...
 
template<typename Label , typename Types >
fcppt::record::label_value_type< fcppt::record::object< Types >, Label > & fcppt::record::get (fcppt::record::object< Types > &_arg)
 Gets an element from a record. More...
 
template<typename Result , typename Function >
Result fcppt::record::init (Function const &_function)
 Initializes a record using a function. More...
 
template<typename Label >
std::string fcppt::record::label_name ()
 Returns the name of a label as a string. More...
 
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. More...
 
template<typename Record1 , typename Record2 >
fcppt::record::disjoint_product< typename std::decay< Record1 >::type, typename std::decay< Record2 >::type > fcppt::record::multiply_disjoint (Record1 &&_record1, Record2 &&_record2)
 Creates the disjoint product of two records. More...
 
template<typename Ch , typename Traits , typename Types >
std::basic_ostream< Ch, Traits > & fcppt::record::operator<< (std::basic_ostream< Ch, Traits > &_stream, fcppt::record::object< Types > const &_record)
 Outputs a record to a stream. More...
 
template<typename Result , typename Arg >
Result fcppt::record::permute (Arg &&_arg)
 Permutes one record into another. More...
 
template<typename Label , typename Types >
void fcppt::record::set (fcppt::record::object< Types > &_arg, fcppt::record::label_value_type< fcppt::record::object< Types >, Label > const &_value)
 Sets an element in a record by copy. More...
 
template<typename Label , typename Types >
void fcppt::record::set (fcppt::record::object< Types > &_arg, fcppt::record::label_value_type< fcppt::record::object< Types >, Label > &&_value)
 Sets an element in a record by move. More...
 

Macro Definition Documentation

◆ FCPPT_RECORD_MAKE_LABEL

#define FCPPT_RECORD_MAKE_LABEL (   name)
Value:
FCPPT_RECORD_DETAIL_MAKE_TAG(\
); \
\
typedef \
fcppt::record::label<\
FCPPT_RECORD_DETAIL_TAG_NAME(\
) \
> \
name
fcppt::strong_typedef< fcppt::string,_ > name
The name of a logger.
Definition: name_fwd.hpp:27

Creates an fcppt::record::label.

Creates an fcppt::record::label, passing it a unique, implementation-defined tag type.

Parameters
nameThe name of the label type.

◆ FCPPT_RECORD_MAKE_LABEL_ARG

#define FCPPT_RECORD_MAKE_LABEL_ARG (   name,
  arg 
)
Value:
template<\
arg\
>\
FCPPT_RECORD_DETAIL_MAKE_TAG(\
); \
\
template<\
arg arg_name\
> \
using \
name \
= \
fcppt::record::label<\
FCPPT_RECORD_DETAIL_TAG_NAME(\
) \
< \
arg_name\
>\
> \
fcppt::strong_typedef< fcppt::string,_ > name
The name of a logger.
Definition: name_fwd.hpp:27

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.

Parameters
nameThe name of the label type.
argThe type of the template parameter.

Typedef Documentation

◆ are_equivalent

template<typename Record1 , typename Record2 >
using fcppt::record::are_equivalent = typedef boost::mpl::and_< boost::mpl::empty< typename fcppt::mpl::set_symmetric_difference< fcppt::record::label_set< Record1 >, fcppt::record::label_set< Record2 > >::type >, typename fcppt::mpl::all_of< fcppt::record::label_set< Record1 >, std::is_same< boost::mpl::at< fcppt::record::element_map< Record1 >, boost::mpl::_1 >, boost::mpl::at< fcppt::record::element_map< Record2 >, boost::mpl::_1 > > >::type >

Tests if two records have the same element maps.

◆ element_map

template<typename Record >
using fcppt::record::element_map = typedef typename fcppt::record::element_map_tpl< Record >::type

The element map of a record.

Template Parameters
RecordMust be an fcppt::record::object.

◆ element_to_label

template<typename Element >
using fcppt::record::element_to_label = typedef typename fcppt::record::element_to_label_tpl< typename std::decay< Element >::type >::type

Extracts the type of an element.

Template Parameters
ElementMust be an fcppt::record::element.

◆ element_to_type

template<typename Element >
using fcppt::record::element_to_type = typedef typename fcppt::record::element_to_type_tpl< typename std::decay< Element >::type >::type

Extracts the label of an element.

Template Parameters
ElementMust be an fcppt::record::element.

◆ element_vector

template<typename Record >
using fcppt::record::element_vector = typedef typename fcppt::record::element_vector_tpl< Record >::type

The elements of record as an MPL vector.

Template Parameters
RecordMust be an fcppt::record::object.

◆ label_set

template<typename Record >
using fcppt::record::label_set = typedef typename fcppt::record::label_set_tpl< Record >::type

The set of labels of a record.

Template Parameters
RecordMust be an fcppt::record::object.

◆ label_value_type

template<typename Record , typename Label >
using fcppt::record::label_value_type = typedef typename fcppt::record::label_value_type_tpl< Record, Label >::type

The value type of a label inside a record.

Returns the type the label Label has in Record.

◆ map_elements

template<typename Record , typename Function >
using fcppt::record::map_elements = typedef fcppt::record::object< typename boost::mpl::transform< fcppt::record::element_vector< Record >, fcppt::record::element< fcppt::record::element_to_label_tpl< boost::mpl::_1 >, boost::mpl::bind< typename boost::mpl::lambda< Function >::type, boost::mpl::_1 > > >::type >

Maps the elements of a vector using a metafunction.

Template Parameters
RecordMust be an fcppt::record::object.
FunctionA metafunction accepting fcppt::record::element as parameters and returning the new mapped types.

◆ map_result

template<typename Record , typename Function >
using fcppt::record::map_result = typedef fcppt::record::map_elements< Record, fcppt::record::detail::map_result< Function, boost::mpl::_ > >

The result of mapping a record.

◆ variadic

template<typename... Types>
using fcppt::record::variadic = typedef fcppt::record::object< boost::mpl::vector< Types... > >

Declares a record using a parameter pack.

Function Documentation

◆ get() [1/2]

template<typename Label , typename Types >
fcppt::record::label_value_type< fcppt::record::object< Types >, Label> const& fcppt::record::get ( fcppt::record::object< Types > const &  _arg)
inline

Gets an element from a record.

Returns the element identified by Label from _arg.

◆ get() [2/2]

template<typename Label , typename Types >
fcppt::record::label_value_type< fcppt::record::object< Types >, Label>& fcppt::record::get ( fcppt::record::object< Types > &  _arg)
inline

Gets an element from a record.

Returns the element identified by Label from _arg.

◆ init()

template<typename Result , typename Function >
Result fcppt::record::init ( Function const &  _function)
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.

Template Parameters
ResultMust be an fcppt::record::object.
FunctionA polymorphic function callable as fcppt::record::label_value_type<Result, L> (fcppt::record::element<L,T>) for every element<L,T> in Result.

◆ label_name()

template<typename Label >
std::string fcppt::record::label_name ( )
inline

Returns the name of a label as a string.

◆ map()

template<typename Record , typename Function >
fcppt::record::map_result< Record, Function> fcppt::record::map ( Record &&  _record,
Function const &  _function 
)
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.

Template Parameters
RecordAn fcppt::record::object.
Functiona polymorphic function that can be called with every type in Record.
See also
fcppt::record::map_result

◆ multiply_disjoint()

template<typename Record1 , typename Record2 >
fcppt::record::disjoint_product< typename std::decay< Record1 >::type, typename std::decay< Record2 >::type> fcppt::record::multiply_disjoint ( Record1 &&  _record1,
Record2 &&  _record2 
)

Creates the disjoint product of two records.

Template Parameters
Record1Must be an fcppt::record::object that is disjoint from Record2.
Record2Must be an fcppt::record::object that is disjoint from Record1.

◆ operator!=()

template<typename Types1 , typename Types2 >
bool fcppt::record::operator!= ( fcppt::record::object< Types1 > const &  _record1,
fcppt::record::object< Types2 > const &  _record2 
)
inline

Compares two records for inequality.

Template Parameters
Types1Must be equivalent to Types2
Types2Must be equivalent to Types1

◆ operator<<()

template<typename Ch , typename Traits , typename Types >
std::basic_ostream< Ch, Traits>& fcppt::record::operator<< ( std::basic_ostream< Ch, Traits > &  _stream,
fcppt::record::object< Types > const &  _record 
)

Outputs a record to a stream.

◆ operator==()

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 Parameters
Types1Must be equivalent to Types2
Types2Must be equivalent to Types1

◆ permute()

template<typename Result , typename Arg >
Result fcppt::record::permute ( Arg &&  _arg)
inline

Permutes one record into another.

Template Parameters
ResultMust be equivalent to Arg, and must be an fcppt::record::object.
ArgMust be equivalent to Result, and must be an fcppt::record::object.

◆ set() [1/2]

template<typename Label , typename Types >
void fcppt::record::set ( fcppt::record::object< Types > &  _arg,
fcppt::record::label_value_type< fcppt::record::object< Types >, Label > const &  _value 
)
inline

Sets an element in a record by copy.

Copies _value to the element identified by Label in _arg.

◆ set() [2/2]

template<typename Label , typename Types >
void fcppt::record::set ( fcppt::record::object< Types > &  _arg,
fcppt::record::label_value_type< fcppt::record::object< Types >, Label > &&  _value 
)
inline

Sets an element in a record by move.

Moves _value to the element identified by Label in _arg.