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.

+3


source to share


3 answers


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.

+2


source


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);

      

+2


source


Using the copy constructor should work:

// construct object of same type as val
StorageT new_val(val);
boost::get(new_val) = 32.0;

      

0


source







All Articles