2.5.1
Freundlich's C++ toolkit
Classes | Typedefs | Functions
fcppt.variant

Description

A class that can hold any object from a fixed set of types.

Motivation

A variant is a type that can hold objects of a fixed set of types, which is sometimes also called a sum type. The closest language feature in C++ are unions, which are very low-level and dangerous to use:

union int_or_float
{
int i;
float f;
};
int_or_float var;
// Undefined behaviour because the union doesn't store anything
//std::cout << var.i << '\n';
// Ok, but doesn't track that the type is int
var.i = 42;
// Undefined behaviour because the union stores an int
//std::cout << var.f << '\n';
auto const print(
[](
int_or_float
)
{
// how do we know which type of object is stored?
}
);
var
);

fcppt::variant fixes the aforementioned problems in the following way:

Consider a variant of an int and a string, for which we provide a print function:

typedef
int
>
string_or_int;
auto const print(
[](
string_or_int const &_v
)
{
_v,
[](
std::string const &_str
)
{
<< "We have a string "
<< _str
<< '\n';
},
[](
int const _i
)
{
<< "We have an int "
<< _i
<< '\n';
}
);
}
);
string_or_int const var(
std::string(
"Hello World"
)
);
var
);

Notice that we do not query which type the variant holds. Instead, we make use of fcppt::variant::match and write out all cases explicitly.

Visitation

A more general way to access variants is called visitation, which is similar to pattern matching. A visitor is a struct or class that uses an overloaded operator() to distinguish between the possible types of a variant.

Suppose we want to define a visitor that does something different for all integral types. The easiest way this can be done is by using std::enable_if.

struct print_visitor
{
template<
typename T
>
typename
std::enable_if<
!std::is_integral<
T
>::value,
void
>::type
operator()(
T const &_value
) const
{
<< "Not integral: "
<< _value
<< '\n';
}
template<
typename T
>
typename
std::enable_if<
std::is_integral<
T
>::value,
void
>::type
operator()(
T const _value
) const
{
<< "Integral: "
<< _value
<< '\n';
}
};

The following code shows how such a visitor is called:

// Prints "Not integral: Hello World".
print_visitor(),
string_or_int(
std::string(
"Hello World"
)
)
);
// Prints "Integral: 42".
print_visitor(),
string_or_int(
42
)
);

fcppt::variant::apply_binary and fcppt::variant::apply_ternary are also provided. These can be used to visit two or three variants at the same time. In this case, the operator() takes two or three arguments, respectively.

Here is a small example for defining a binary visitor:

string_or_int const v(
std::string(
"Hello World"
)
);
string_or_int const u(
42
);
// Does a binary visitation.
// Prints "Hello World" 42.
[](
auto const &_val1,
auto const &_val2
)
{
<< _val1
<< ' '
<< _val2
<< '\n';
},
v,
u
);

Non-const visitation, which means that the visited variant can be modified, is also supported.

struct visitor
{
// operator() takes T as non const ref
template<
typename T
>
void
operator()(
T &_val
) const
{
// reset _val to the default value
_val = T();
}
};
string_or_int v(
std::string(
"Hello World"
)
);
visitor(),
v
);
// only prints a newline because the string contains nothing anymore
<<
std::string
>(
v
) << '\n';

Access

Visitation and matching are the most common ways to access a variant. The other ways are:

Design

While the design of fcppt::variant is similar to boost::variant, there are some key differences:

Header files

Header file Description
object_fwd.hpp Contains variants's declaration.
object_decl.hpp Contains variant's definition.
object_impl.hpp Contains the definition of variants's member functions.
object.hpp The same as object_impl.hpp.
apply_unary.hpp Contains fcppt::variant::apply_unary for unary visitation.
apply_binary.hpp Contains fcppt::variant::apply_binary for binary visitation.
apply_ternary.hpp Contains fcppt::variant::apply_ternary for ternary visitation.
compare.hpp Contains fcppt::variant::compare.
comparison.hpp Includes equal.hpp and not_equal.hpp.
equal.hpp Contains operator==.
exception.hpp Contains fcppt::variant::exception, the base class for every variant exception.
get_exn.hpp Contains fcppt::variant::get_exn.
get_unsafe.hpp Contains fcppt::variant::get_unsafe which does the same thing as the fcppt::variant::object::get_unsafe member function.
holds_type.hpp Contains the fcppt::variant::holds_type function to check if a type is held by the variant.
invalid_get.hpp Contains fcppt::variant::invalid_get, which might be thrown by fcppt::variant::get_exn.
less.hpp Contains operator<.
match.hpp Contains fcppt::variant::match.
not_equal.hpp Contains operator!=.
output.hpp Contains operator<< for output.
to_optional.hpp Contains fcppt::variant::to_optional.
to_optional_ref.hpp Contains fcppt::variant::to_optional_ref.
type_info.hpp Contains fcppt::variant::type_info.
variadic_fwd.hpp Contains fcppt::variant::variadic and declares fcppt::variant::object.
variadic.hpp Includes fcppt/variant/object_fwd.hpp and defines fcppt::variant::object.

Classes

class  fcppt::variant::exception
 The base exception class for variant exceptions. More...
 
class  fcppt::variant::invalid_get
 Thrown by fcppt::variant::get_exn. More...
 
class  fcppt::variant::object< Types >
 A class that can hold any object from a fixed set of types. More...
 
struct  fcppt::variant::object< Types >>
 A metafunction returning the types of a variant. More...
 

Typedefs

typedef unsigned fcppt::variant::size_type
 An integer type used to describe a type index. More...
 
template<typename Variant >
using fcppt::variant::types_of = typename fcppt::variant::types_of_tpl< Variant >::type
 The types of a variant. More...
 
template<typename... Types>
using fcppt::variant::variadic = fcppt::variant::object< boost::mpl::vector< Types... > >
 Declares a variant using a parameter pack. More...
 

Functions

template<typename Operation , typename Variant1 , typename Variant2 >
decltype(auto) fcppt::variant::apply_binary (Operation &&_op, Variant1 &&_obj1, Variant2 &&_obj2)
 Passes the contents of two variants to a polymorphic function. More...
 
template<typename Operation , typename Variant1 , typename Variant2 , typename Variant3 >
decltype(auto) fcppt::variant::apply_ternary (Operation &&_op, Variant1 &&_obj1, Variant2 &&_obj2, Variant3 &&_obj3)
 Passes the contents of three variants to a polymorphic function. More...
 
template<typename Operation , typename Variant >
decltype(auto) fcppt::variant::apply_unary (Operation &&_op, Variant &&_obj)
 Passes the contents of a variant to a polymorphic function. More...
 
template<typename Types , typename Compare >
bool fcppt::variant::compare (fcppt::variant::object< Types > const &_left, fcppt::variant::object< Types > const &_right, Compare const &_compare)
 Compares two variants using a Compare function. More...
 
template<typename Elements >
fcppt::string fcppt::variant::current_type_name (fcppt::variant::object< Elements > const &_variant)
 Returns the type name of the current type. More...
 
template<typename Types >
bool fcppt::variant::operator== (fcppt::variant::object< Types > const &_left, fcppt::variant::object< Types > const &_right)
 Compares two variants for equality. More...
 
template<typename Type , typename Elements >
Type & fcppt::variant::get_exn (fcppt::variant::object< Elements > &_object)
 Free get function. More...
 
template<typename Type , typename Elements >
Type const & fcppt::variant::get_exn (fcppt::variant::object< Elements > const &_object)
 Free get function. More...
 
template<typename Type , typename Elements >
Type & fcppt::variant::get_unsafe (fcppt::variant::object< Elements > &_object)
 Free get function. More...
 
template<typename Type , typename Elements >
Type const & fcppt::variant::get_unsafe (fcppt::variant::object< Elements > const &_object)
 Free get function. More...
 
template<typename Type , typename Elements >
bool fcppt::variant::holds_type (fcppt::variant::object< Elements > const &_variant)
 Checks if a type is held by a variant. More...
 
template<typename Types >
bool fcppt::variant::operator< (fcppt::variant::object< Types > const &_left, fcppt::variant::object< Types > const &_right)
 Tests if one variant is less than another. More...
 
template<typename Variant , typename... Functions>
decltype(auto) fcppt::variant::match (Variant &&_variant, Functions const &... _functions)
 Matches a variant with a function for each element type. More...
 
template<typename Types >
bool fcppt::variant::operator!= (fcppt::variant::object< Types > const &_a, fcppt::variant::object< Types > const &_b)
 Compares two variants for inequality. More...
 
template<typename Types , typename Ch , typename Traits >
std::basic_ostream< Ch, Traits > & fcppt::variant::operator<< (std::basic_ostream< Ch, Traits > &_stream, fcppt::variant::object< Types > const &_object)
 Outputs the value held by the variant to a basic_ostream. More...
 
template<typename Type , typename Variant >
fcppt::optional::object< Type > fcppt::variant::to_optional (Variant &&_variant)
 Converts a variant and a type to an optional. More...
 
template<typename Type , typename Variant >
fcppt::optional::reference< Type > fcppt::variant::to_optional_ref (Variant &_variant)
 Converts a variant and a type to an optional reference. More...
 
template<typename Types >
std::type_info const & fcppt::variant::type_info (fcppt::variant::object< Types > const &_variant)
 Returns an std::type_info of the held type. More...
 
template<typename Variant >
fcppt::string fcppt::variant::types_string ()
 Returns the types of a variant as a string. More...
 

Typedef Documentation

◆ size_type

typedef unsigned fcppt::variant::size_type

An integer type used to describe a type index.

See also
fcppt::variant::object::type_index

◆ types_of

template<typename Variant >
using fcppt::variant::types_of = typedef typename fcppt::variant::types_of_tpl< Variant >::type

The types of a variant.

◆ variadic

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

Declares a variant using a parameter pack.

Function Documentation

◆ apply_binary()

template<typename Operation , typename Variant1 , typename Variant2 >
decltype( auto ) fcppt::variant::apply_binary ( Operation &&  _op,
Variant1 &&  _obj1,
Variant2 &&  _obj2 
)
inline

Passes the contents of two variants to a polymorphic function.

Calls _op.operator()(T,U) where T is the type held by _obj1 and U is the type held by _obj2.

Template Parameters
OperationA polymorphic binary function
Variant1Must be an fcppt::variant::object
Variant2Must be an fcppt::variant::object

◆ apply_ternary()

template<typename Operation , typename Variant1 , typename Variant2 , typename Variant3 >
decltype( auto ) fcppt::variant::apply_ternary ( Operation &&  _op,
Variant1 &&  _obj1,
Variant2 &&  _obj2,
Variant3 &&  _obj3 
)
inline

Passes the contents of three variants to a polymorphic function.

Calls _op.operator()(T, U, V) where T is the type held by _obj1, U is the type held by _obj2 and V is the type held by _obj3.

Template Parameters
OperationA polymorphic ternary function
Variant1Must be an fcppt::variant::object
Variant2Must be an fcppt::variant::object
Variant3Must be an fcppt::variant::object

◆ apply_unary()

template<typename Operation , typename Variant >
decltype( auto ) fcppt::variant::apply_unary ( Operation &&  _op,
Variant &&  _obj 
)

Passes the contents of a variant to a polymorphic function.

Calls _op.operator()(T) where T is the type held _obj.

Template Parameters
OperationA polymorphic function that can accept any type of Variant
VariantMust be an fcppt::variant::object

◆ compare()

template<typename Types , typename Compare >
bool fcppt::variant::compare ( fcppt::variant::object< Types > const &  _left,
fcppt::variant::object< Types > const &  _right,
Compare const &  _compare 
)
inline

Compares two variants using a Compare function.

Compares _left and _right using _compare. The two variants are equal if they hold the same type T and _compare(_left.get<T>(), _right.get<T>()) holds.

Parameters
_leftThe first variant
_rightThe second variant
_compareThe function to use for comparison

◆ current_type_name()

template<typename Elements >
fcppt::string fcppt::variant::current_type_name ( fcppt::variant::object< Elements > const &  _variant)

Returns the type name of the current type.

◆ get_exn() [1/2]

template<typename Type , typename Elements >
Type& fcppt::variant::get_exn ( fcppt::variant::object< Elements > &  _object)

Free get function.

Equal to _object.get<Type>()

See also
fcppt::variant::object::get()

◆ get_exn() [2/2]

template<typename Type , typename Elements >
Type const& fcppt::variant::get_exn ( fcppt::variant::object< Elements > const &  _object)

Free get function.

Equal to _object.get<Type>()

See also
fcppt::variant::object::get() const

◆ get_unsafe() [1/2]

template<typename Type , typename Elements >
Type& fcppt::variant::get_unsafe ( fcppt::variant::object< Elements > &  _object)

Free get function.

Equal to _object.get<Type>()

See also
fcppt::variant::object::get()

◆ get_unsafe() [2/2]

template<typename Type , typename Elements >
Type const& fcppt::variant::get_unsafe ( fcppt::variant::object< Elements > const &  _object)

Free get function.

Equal to _object.get<Type>()

See also
fcppt::variant::object::get() const

◆ holds_type()

template<typename Type , typename Elements >
bool fcppt::variant::holds_type ( fcppt::variant::object< Elements > const &  _variant)
inline

Checks if a type is held by a variant.

The currently held type of a variant is the type passed to its constructor or assignment operator. A type T can be held by a variant<Set> if T is a member of Set.

This function checks if Type is held by _variant.

Template Parameters
TypeThe type to check for which must be a possible type for the variant
ElementsThe types of the variant
Parameters
_variantThe variant to check
Returns
If the type is held by the variant

◆ match()

template<typename Variant , typename... Functions>
decltype( auto ) fcppt::variant::match ( Variant &&  _variant,
Functions const &...  _functions 
)
inline

Matches a variant with a function for each element type.

Matches _variant with _functions. The functions must be listed in the order the types appear in the variant.

◆ operator!=()

template<typename Types >
bool fcppt::variant::operator!= ( fcppt::variant::object< Types > const &  _a,
fcppt::variant::object< Types > const &  _b 
)

Compares two variants for inequality.

Compares _a and _b for inequality. Equal to !(_a == _b). This function requires all possible types of the variant to be equality comparable.

Parameters
_aThe first variant
_bThe second variant

◆ operator<()

template<typename Types >
bool fcppt::variant::operator< ( fcppt::variant::object< Types > const &  _left,
fcppt::variant::object< Types > const &  _right 
)

Tests if one variant is less than another.

Tests if _left is less than _right. Let val_left be the value stored in _left and val_right the value stored in _right. _left is less than _right iff (_left.type_index(), val_left) is lexicographically before (_right.type_index(), val_right). This also implies that every type of the variant must be less comparable.

Parameters
_leftThe first variant
_rightThe second variant

◆ operator<<()

template<typename Types , typename Ch , typename Traits >
std::basic_ostream< Ch, Traits>& fcppt::variant::operator<< ( std::basic_ostream< Ch, Traits > &  _stream,
fcppt::variant::object< Types > const &  _object 
)
inline

Outputs the value held by the variant to a basic_ostream.

Outputs the value held by _object to _stream. This function requires all possibles types to be printable.

Parameters
_streamThe stream to output to
_objectThe variant to output
Returns
_stream

◆ operator==()

template<typename Types >
bool fcppt::variant::operator== ( fcppt::variant::object< Types > const &  _left,
fcppt::variant::object< Types > const &  _right 
)

Compares two variants for equality.

Compares _left and _right for equality. The two variants are equal if they hold the same type and the values compare equal. This function requires all possible types of the variant to be equality comparable.

Parameters
_leftThe first variant
_rightThe second variant

◆ to_optional()

template<typename Type , typename Variant >
fcppt::optional::object< Type> fcppt::variant::to_optional ( Variant &&  _variant)

Converts a variant and a type to an optional.

◆ to_optional_ref()

template<typename Type , typename Variant >
fcppt::optional::reference< Type> fcppt::variant::to_optional_ref ( Variant &  _variant)

Converts a variant and a type to an optional reference.

◆ type_info()

template<typename Types >
std::type_info const& fcppt::variant::type_info ( fcppt::variant::object< Types > const &  _variant)

Returns an std::type_info of the held type.

◆ types_string()

template<typename Variant >
fcppt::string fcppt::variant::types_string ( )
inline

Returns the types of a variant as a string.

Template Parameters
VariantMust be an fcppt::variant::object.