rttr::variant Class Reference

The variant class allows to store data of any type and convert between these types transparently. More...

#include <variant.h>

Public Member Functions

 variant ()
 Constructs an invalid variant. More...
 
template<typename T , typename Tp = detail::decay_variant_t<T>>
 variant (T &&val)
 Constructs a new variant with the new value val. More...
 
 variant (const variant &other)
 Constructs a new variant object from the given variant other. More...
 
 variant (variant &&other)
 Constructs a new variant via move constructor. More...
 
 ~variant ()
 Destroys the variant and the contained object. More...
 
template<typename T >
bool can_convert () const
 Returns true if the contained value can be converted to the given type T. More...
 
bool can_convert (const type &target_type) const
 Returns true if the contained value can be converted to the given type target_type; otherwise false. More...
 
void clear ()
 When the variant contains a value, then this function will clear the content. More...
 
bool convert (const type &target_type)
 Converts the containing variant internally to the given type target_type. More...
 
template<typename T >
convert (bool *ok=nullptr) const
 Converts the containing data to a new value of type T and return this value. More...
 
template<typename T >
bool convert (T &value) const
 Converts the containing data to the given value value and returns a bool flag that indicated whether the conversion was successful or not. More...
 
variant_array_view create_array_view () const
 Creates a variant_array_view from the containing value, when the type or its raw type or the wrapped type is an array. More...
 
type get_type () const
 Returns the type object of underlying data. More...
 
template<typename T >
const T & get_value () const
 Returns a reference to the containing value as type T. More...
 
bool is_array () const
 When the type or its raw type or the wrapped type is an array, then this function will return true, otherwise false. More...
 
template<typename T >
bool is_type () const
 Returns true if the containing variant data is of the given template type T. More...
 
bool is_valid () const
 Returns true if this variant is valid, that means the variant is holding some data. More...
 
 operator bool () const
 Convenience function to check if this variant is valid or not. More...
 
bool operator!= (const variant &other) const
 Compares this variant with other and returns true if they are not equal; otherwise returns false. More...
 
bool operator< (const variant &other) const
 Compares this variant with other and returns true if this is less than other, otherwise returns false. More...
 
template<typename T , typename Tp = detail::decay_variant_t<T>>
variantoperator= (T &&other)
 Assigns the value of the other object to this variant. More...
 
variantoperator= (variant &&other)
 Assigns the value of the other variant to this variant. More...
 
variantoperator= (const variant &other)
 Assigns the value of the other variant to this variant. More...
 
bool operator== (const variant &other) const
 Compares this variant with other and returns true if they are equal; otherwise returns false. More...
 
void swap (variant &other)
 Swaps the content of this variant with other variant. More...
 
bool to_bool () const
 Returns the variant as a bool if this variant is of type bool. More...
 
double to_double (bool *ok=nullptr) const
 Returns the containing variant as a double when the type is a double. More...
 
float to_float (bool *ok=nullptr) const
 Returns the containing variant as a float when the type is a float. More...
 
int to_int (bool *ok=nullptr) const
 Returns the containing variant as an int when the type is an integer. More...
 
int16_t to_int16 (bool *ok=nullptr) const
 Returns the containing variant as an int16_t when the type is an int16_t. More...
 
int32_t to_int32 (bool *ok=nullptr) const
 Returns the containing variant as an int32_t when the type is an int32_t. More...
 
int64_t to_int64 (bool *ok=nullptr) const
 Returns the containing variant as an int64_t when the type is an int64_t. More...
 
int8_t to_int8 (bool *ok=nullptr) const
 Returns the containing variant as an int8_t when the type is an int8_t. More...
 
std::string to_string (bool *ok=nullptr) const
 Returns the containing variant as a std::string when the type is a std::string. More...
 
uint16_t to_uint16 (bool *ok=nullptr) const
 Returns the containing variant as an uint16_t when the type is an uint16_t. More...
 
uint32_t to_uint32 (bool *ok=nullptr) const
 Returns the containing variant as an uint32_t when the type is an uint32_t. More...
 
uint64_t to_uint64 (bool *ok=nullptr) const
 Returns the containing variant as an uint64_t when the type is an uint64_t. More...
 
uint8_t to_uint8 (bool *ok=nullptr) const
 Returns the containing variant as an uint8_t when the type is an uint8_t. More...
 

Detailed Description

The variant class allows to store data of any type and convert between these types transparently.

This class serves as container for any given single type. It can hold one value at a time (using containers you can hold multiple types e.g. std::vector<int>). Remark that the content is copied into the variant class. Even raw arrays (e.g. int[10]) are copied. However, the internal implementation of variant has an optimization for storing small types, which avoid heap allocation.

The main purpose of this class is to be the return value for property and method invokes or as container for storing meta data.

Copying and Assignment

A variant object can be copied and assigned, however each copy will perform a copy of the contained value.

Typical Usage

variant var;
var = 23; // copy integer
int x = var.to_int(); // x = 23
var = "Hello World"; // var contains now a std::string (implicit conversion of string literals to std::string)
int y = var.to_int(); // y = 0, because invalid conversion
var = "42"; // contains a std::string
std::cout << var.to_int(); // convert std::string to integer and prints "42"
int my_array[100];
var = my_array; // copies the content of my_array into var
auto& arr = var.get_value<int[100]>(); // extracts the content of var by reference

Extract Value

For extracting a value out of a variant you can use the get_value() function. This will return a const reference to the contained value. However, you must instantiated this function with the exact type of the stored value, otherwise undefined behaviour will occur. Therefore you should check it's type before extracting with is_type<T>().

See following example:

struct custom_type
{
//...
};
variant var = custom_type{};
if (var.is_type<custom_type>()) // yields to true
const custom_type& value = var.get_value<custom_type>(); // extracts the value by reference

Conversion

The variant class offers three possibilities to convert to a new type.

  • convert(const type& target_type) - convert the variant internally to a new type
  • convert<T>(bool *ok) - convert the contained value to an internally default created value of type T
  • convert<T>(T& value) - convert the contained value to a given value of type T

See following example code:

variant var = 500; // var contains an int
if(var.can_convert<std::string>()) // check whether conversion is possible
{
var.convert(type::get<std::string>()); // var contains now a std::string, with value => "23"
var.is_type<std::string>(); // yields to 'true'
}
bool ok = false;
int int_value = var.convert<int>(&ok); // int_value == 23, ok yields to 'true'
// or
uint8_t small_int = 0;
bool result = var.convert<uint8_t>(small_int); // result == false, because small_int cannot hold the value '500'
Remarks
It is possible that can_convert() will return true, but convert() will actually fail and return false. The reason for this is can_convert() will return the general ability of converting between types given suitable data; when no suitable data is given, the conversion cannot be performed.

A good example is the conversion from std::string to int.

variant var = "Answer: 42";
var.can_convert<int>(); // yields to 'true'
int number;
bool result = var.convert(number); // yields to 'false', because the string contains non-numeric characters

Hence, it is important to have both functions return true for a successful conversion.

Custom Converter

The variant class allows to convert from and to user-defined types, therefore you have to register a conversion function.

See following example code:

std::string converter_func(const custom_type& value, bool& ok)
{
ok = true;
// convert value to std::string
return std::string(...);
}
//...
variant var = custom_type(...);
var.can_convert<std::string>(); // return 'false'
// register the conversion function
var.can_convert<std::string>(); // return 'true'
var.to_string(); // converts from 'custom_type' to 'std::string'

For more information see type::register_converter_func()

See also
variant_array_view

Constructor & Destructor Documentation

rttr::variant::variant ( )

Constructs an invalid variant.

That means a valid which contains no data.

See also
is_valid()
template<typename T , typename Tp = detail::decay_variant_t<T>>
rttr::variant::variant ( T &&  val)

Constructs a new variant with the new value val.

The value will be copied or moved into the variant.

rttr::variant::variant ( const variant other)

Constructs a new variant object from the given variant other.

rttr::variant::variant ( variant &&  other)

Constructs a new variant via move constructor.

rttr::variant::~variant ( )

Destroys the variant and the contained object.

Member Function Documentation

template<typename T >
bool rttr::variant::can_convert ( ) const

Returns true if the contained value can be converted to the given type T.

Otherwise false.

Returns
True if this variant can be converted to T; otherwise false.
bool rttr::variant::can_convert ( const type target_type) const

Returns true if the contained value can be converted to the given type target_type; otherwise false.

The returned value indicates that a conversion is in general possible. However a conversion might still fail when doing the actual conversion with convert(). An example is the conversion from a string to a number. When the string does not contain non-numeric characters, the conversion will not succeed.

Returns
True if this variant can be converted to target_type; otherwise false.
void rttr::variant::clear ( )

When the variant contains a value, then this function will clear the content.

Remarks
After calling this function is_valid() will return false.
bool rttr::variant::convert ( const type target_type)

Converts the containing variant internally to the given type target_type.

When the conversion was successfully the function will return true. When the conversion fails, then the containing variant value stays the same and the function will return false.

A variant containing a pointer to a custom type will be also converted and return true for this function, if a rttr_cast to the type described by target_type would succeed.

See therefore following example code:

struct base { virtual ~base(){} };
struct derived : base { };
derived d;
variant var = static_cast<base*>(&d); // var contains a '*base' ptr
bool ret = var.convert(type::get<derived*>()); // yields to 'true'
var.is_type<derived*>(); // yields to 'true'
See also
can_convert()
Returns
True if this variant can be converted to target_type; otherwise false.
template<typename T >
T rttr::variant::convert ( bool *  ok = nullptr) const

Converts the containing data to a new value of type T and return this value.

If ok is non-null: *ok is set to true when the value was successfully converted to T; otherwise *ok is set to false. The type T must meet the requirement to be default constructible.

variant val = 12;
if (val.can_convert<float>())
{
bool ok = false;
float result = val.convert<float>(&ok);
if (ok)
// ...
}
Remarks
Before doing the conversion you should check whether it is in general possible to convert to type T with the function can_convert(). When the conversion fails, a default constructed value of type T is returned.
See also
can_convert()
Returns
The converted value as type T.
template<typename T >
bool rttr::variant::convert ( T &  value) const

Converts the containing data to the given value value and returns a bool flag that indicated whether the conversion was successful or not.

When you need to convert to a type which cannot be default constructed use this function.

See following example code:

variant val = 12;
if (val.can_convert<custom_type>())
{
custom_type obj(42); // non-default ctor type
bool result = val.convert(obj);
if (result)
// ...
}
Remarks
Before doing the conversion you should check whether it is in general possible to convert to type T with the function can_convert()
See also
can_convert()
Returns
True if the contained data could be converted to value; otherwise false.
variant_array_view rttr::variant::create_array_view ( ) const

Creates a variant_array_view from the containing value, when the type or its raw type or the wrapped type is an array.

Otherwise a default constructed variant_array_view will be returned. For shorten this check, use the function is_array().

A typical example is the following:

int obj_array[100];
variant var = obj_array; // copies the content of obj_array into var
variant_array_view array = var.create_array_view(); // copies the content of var to a variant_array object
auto x = array.get_size(); // set x to 100
array.set_value(0, 42); // set the first index to the value 42
See also
can_convert(), convert()
Remarks
This function will return an invalid object, when the type is no array.
Returns
A variant_array_view object.
type rttr::variant::get_type ( ) const

Returns the type object of underlying data.

Remarks
When the variant has not stored any data, then an invalid type object is returned.
Returns
type of the underlying data type.
template<typename T >
const T& rttr::variant::get_value ( ) const

Returns a reference to the containing value as type T.

struct custom_type
{
//...
};
variant var = custom_type{};
if (var.is_type<custom_type>()) // yields to true
const custom_type& value = var.get_value<custom_type>(); // extracts the value by reference
Remarks
Only call this method when it is possible to return the containing value as the given type T. Use therefore the method is_type(). Otherwise the call leads to undefined behaviour. Also make sure you don't clean this variant, when you still hold a reference to the containing value.
See also
is_type()
Returns
A reference to the stored value.
bool rttr::variant::is_array ( ) const

When the type or its raw type or the wrapped type is an array, then this function will return true, otherwise false.

Returns
True if the containing value is an array; otherwise false.
template<typename T >
bool rttr::variant::is_type ( ) const

Returns true if the containing variant data is of the given template type T.

Returns
True if variant data is of type T, otherwise false.
bool rttr::variant::is_valid ( ) const

Returns true if this variant is valid, that means the variant is holding some data.

When the variant doesn't hold any data it will return false.

Remarks
A variant can also hold void data, this is used to indicate that a method call, which has no return value, was successfully. In this case, there is no data actually stored, but this function will return true.
Returns
True if this variant is valid, otherwise false.
rttr::variant::operator bool ( ) const
explicit

Convenience function to check if this variant is valid or not.

See also
is_valid()
Returns
True if this variant is valid, otherwise false.
bool rttr::variant::operator!= ( const variant other) const

Compares this variant with other and returns true if they are not equal; otherwise returns false.

Remarks
In order to use this function with template types, like std::tuple<int, std::string>, you need to register the comparison operator to the type system with type::register_comparators<T>(). The reason for that is, template types might define the != operator, but not the contained template type.
See also
operator==
Returns
A boolean with value true, that indicates both variant's are not equal, otherwise false.
bool rttr::variant::operator< ( const variant other) const

Compares this variant with other and returns true if this is less than other, otherwise returns false.

The variant uses the less than operator of the containing type. When other is not of the same type as the containing type, it will try to convert to it and do then the less than check.

Remarks
In order to use this function with template types, like std::tuple<int, std::string>, you need to register the comparison operator to the type system with type::register_comparators<T>(). The reason for that is, template types might define the < operator, but not the contained template type.
See also
operator>
Returns
A boolean with value true, that indicates that this variant is less than other, otherwise false.
template<typename T , typename Tp = detail::decay_variant_t<T>>
variant& rttr::variant::operator= ( T &&  other)

Assigns the value of the other object to this variant.

Returns
A reference to the variant with the new data.
variant& rttr::variant::operator= ( variant &&  other)

Assigns the value of the other variant to this variant.

Returns
A reference to the variant with the new data.
variant& rttr::variant::operator= ( const variant other)

Assigns the value of the other variant to this variant.

Returns
A reference to the variant with the new data.
bool rttr::variant::operator== ( const variant other) const

Compares this variant with other and returns true if they are equal; otherwise returns false.

The variant uses the equality operator of the containing type to check for equality. When other is not of the same type as the containing type, it will try to convert to it and do then the equality check.

Remarks
In order to use this function with template types, like std::tuple<int, std::string>, you need to register the comparison operator to the type system with type::register_comparators<T>(). The reason for that is, template types might define the == operator, but not the contained template type.
See also
operator!=
Returns
A boolean with value true, that indicates both variant's are equal, otherwise false.
void rttr::variant::swap ( variant other)

Swaps the content of this variant with other variant.

bool rttr::variant::to_bool ( ) const

Returns the variant as a bool if this variant is of type bool.

Returns true if the variant contains an arithmetic type which value is non-zero or if the variant contains a std::string and its lower-case content is not one of the following: "" (empty), "0" or "false"; otherwise returns false.

Also any user-defined conversion function from the source type to bool will be executed when necessary.

See also
can_convert(), is_type()
Returns
A bool value.
double rttr::variant::to_double ( bool *  ok = nullptr) const

Returns the containing variant as a double when the type is a double.

When the variant contains an arithmetic type or an std::string then a conversion to double will be tried. Also any user-defined conversion function from the source type to double will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an double; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than double, the conversion will fail. Precision loss, such as in conversion from double to float on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A double value.
float rttr::variant::to_float ( bool *  ok = nullptr) const

Returns the containing variant as a float when the type is a float.

When the variant contains an arithmetic type or an std::string then a conversion to float will be tried. Also any user-defined conversion function from the source type to float will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an float; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than float, the conversion will fail. Precision loss, such as in conversion from double to float on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A float value.
int rttr::variant::to_int ( bool *  ok = nullptr) const

Returns the containing variant as an int when the type is an integer.

When the variant contains an arithmetic type or an std::string then a conversion to int will be tried. Also any user-defined conversion function from the source type to int will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an int; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than int, the conversion will fail. Precision loss, such as in conversion from floating-point to int on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
An int value.
int16_t rttr::variant::to_int16 ( bool *  ok = nullptr) const

Returns the containing variant as an int16_t when the type is an int16_t.

When the variant contains an arithmetic type or an std::string then a conversion to int16_t will be tried. Also any user-defined conversion function from the source type to int16_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an int16_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than int16_t, the conversion will fail. Precision loss, such as in conversion from floating-point to int16_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A int16_t value.
int32_t rttr::variant::to_int32 ( bool *  ok = nullptr) const

Returns the containing variant as an int32_t when the type is an int32_t.

When the variant contains an arithmetic type or an std::string then a conversion to int32_t will be tried. Also any user-defined conversion function from the source type to int32_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an int32_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than int32_t, the conversion will fail. Precision loss, such as in conversion from floating-point to int32_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A int32_t value.
int64_t rttr::variant::to_int64 ( bool *  ok = nullptr) const

Returns the containing variant as an int64_t when the type is an int64_t.

When the variant contains an arithmetic type or an std::string then a conversion to int64_t will be tried. Also any user-defined conversion function from the source type to int64_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an int64_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than int64_t, the conversion will fail. Precision loss, such as in conversion from floating-point to int64_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A int64_t value.
int8_t rttr::variant::to_int8 ( bool *  ok = nullptr) const

Returns the containing variant as an int8_t when the type is an int8_t.

When the variant contains an arithmetic type or an std::string then a conversion to int8_t will be tried. Also any user-defined conversion function from the source type to int8_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an int8_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than int8_t, the conversion will fail. Precision loss, such as in conversion from floating-point to int8_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A int8_t value.
std::string rttr::variant::to_string ( bool *  ok = nullptr) const

Returns the containing variant as a std::string when the type is a std::string.

When the variant contains an arithmetic type then a conversion to std::string will be done. Also any user-defined conversion function from the source type to std::string will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an std::string; otherwise *ok is set to false.

See also
can_convert(), is_type()
Returns
A std::string value.
uint16_t rttr::variant::to_uint16 ( bool *  ok = nullptr) const

Returns the containing variant as an uint16_t when the type is an uint16_t.

When the variant contains an arithmetic type or an std::string then a conversion to uint16_t will be tried. Also any user-defined conversion function from the source type to uint16_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an uint16_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than uint16_t, the conversion will fail. Also a loss of signedness is not allowed, that means a negative signed integer cannot be converted to uint16_t. Precision loss, such as in conversion from floating-point to uint16_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A uint16_t value.
uint32_t rttr::variant::to_uint32 ( bool *  ok = nullptr) const

Returns the containing variant as an uint32_t when the type is an uint32_t.

When the variant contains an arithmetic type or an std::string then a conversion to uint32_t will be tried. Also any user-defined conversion function from the source type to uint32_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an uint32_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than uint32_t, the conversion will fail. Also a loss of signedness is not allowed, that means a negative signed integer cannot be converted to uint32_t. Precision loss, such as in conversion from floating-point to uint32_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A uint32_t value.
uint64_t rttr::variant::to_uint64 ( bool *  ok = nullptr) const

Returns the containing variant as an uint64_t when the type is an uint64_t.

When the variant contains an arithmetic type or an std::string then a conversion to uint64_t will be tried. Also any user-defined conversion function from the source type to uint64_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an uint8_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than uint64_t, the conversion will fail. Also a loss of signedness is not allowed, that means a negative signed integer cannot be converted to uint64_t. Precision loss, such as in conversion from floating-point to uint64_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A uint64_t value.
uint8_t rttr::variant::to_uint8 ( bool *  ok = nullptr) const

Returns the containing variant as an uint8_t when the type is an uint8_t.

When the variant contains an arithmetic type or an std::string then a conversion to uint8_t will be tried. Also any user-defined conversion function from the source type to uint8_t will be executed when necessary.

If ok is non-null: *ok is set to true if the value could be converted to an uint8_t; otherwise *ok is set to false.

Remarks
A value overflow is not allowed, so if the internal value is larger than uint8_t, the conversion will fail. Also a loss of signedness is not allowed, that means a negative signed integer cannot be converted to uint8_t. Precision loss, such as in conversion from floating-point to uint8_t on platforms where they differ in size is allowed. A conversion from std::string which contains non-numeric characters will fail.
See also
can_convert(), is_type()
Returns
A uint8_t value.

The documentation for this class was generated from the following file: