How to get the current type of a variant and define new variables of this type
I have an impulse :: variant of types like:
typedef boost::variant< uint8_t, int8_t, uint16_t, int16_t,
uint32_t, int32_t, float, double, std::string > StorageTt;
A variable is StorageTt
, say, val
set to one of these storage types later in my code. I would like to get the type that currently contains in val
order to define more variables of the same type. So if val
currently is uint16_t
, I want to do something like:
typedef decltype(typeid(val)) StorageTt;
StorageTt new_val = 42; // new_val should be a uint16_t
but that gives the const type_info
type const type_info
. I know what I can do:
switch (val.which()) {
case 0: // uint8_t
case 1: //...
but I would rather avoid the long switch statement because I have to do it multiple times.
source to share
You can do something like this with a visitor functor with a call statement pattern:
struct MyVisitor : public boost::static_visitor<>
{
template <typename StorageT>
void operator()(const StorageT&) const
{
StorageT new_val = 32; // declare variable with same type
doSomethingWith(new_val); // do something with it
}
};
Apply it to the variation val
like so:
boost::apply_visitor(MyVisitor(), val);
Link:
I don't know how to replace the functor with the standard C ++ 14 lambda.
source to share
You cannot do this. Variables are syntactic constructs. These are names for programmatic objects. The names only exist in the source code.
The workflow looks like this. First you write the source. Then you compile it, run the program and do some things like retrieving a value from an object boost::variant
. At this stage, you cannot determine the names. There is no source, names, syntax. There are only objects.
If you need a new object of the same type as the one obtained from the variant then StorageT new_val(val);
creates exactly that (the new object is hidden in new_val
, you access it with boost::get
or boost::apply_visitor
or whatever).
If you want to perform an action on whatever variation you have, and all actions look the same, and only their types are different (they are not the same, since the types are different, they look the same) and you want to avoid writing the same type of things multiple times, then, of course templates are your friends. boost::apply_visitor
c template<typename> operator()
is correct:
struct my_assignment_visitor: public boost::static_visitor<>
{
template <typename T> void operator()(T & var, double val) const
{
var = val;
}
};
boost::apply_visitor(my_assignment_visitor(), new_val, 32.0);
source to share