I want to construct boost::variant
s containing default-constructed values, specified with a type index - without writing my own switch statement over the type index.
I figure this must be possible, somehow, with MPL?
To clarify though, the index is not a compile-time constant expression.
The use case is that I need to construct a variant which will later be replaced with one containing the correct value, but at this point I only know the type index. Think of it as a lazy deserialisation problem.
You need to use the variant::types
typedef. This gives you an MPL compatible sequence which we can then use with mpl::at
and a template to do our bidding. This does the trick:
#include <string>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
template<typename U, typename V>
void construct_in(V& v) {
v = U();
// modern
// v = U{};
}
int main()
{
typedef boost::variant<int, std::string> variant;
typedef boost::mpl::at<variant::types, boost::mpl::int_<1>>::type pos;
variant v;
// use type deduction
construct_in<pos>(v);
// does not throw, does work
std::string& s =boost::get<std::string>(v);
return 0;
}
Here goes the runtime-variant:
#include <string>
#include <vector>
#include <functional>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/for_each.hpp>
typedef boost::variant<int, std::string> variant;
typedef variant::types types;
typedef std::vector< std::function<void(variant&)> > fvec;
template<typename U, typename V>
void construct_in(V& v) {
v = U{};
}
struct build_and_add {
fvec* funcs;
template<typename T>
void operator()(T) {
funcs->push_back(&construct_in<T, variant>);
}
};
int main()
{
variant v;
std::vector< std::function<void(variant&)> > funcs;
// cannot use a lambda, would need to be polymorphic
build_and_add f = {&funcs};
boost::mpl::for_each<types>(f);
// this is runtime!
int i = 1;
funcs[i](v);
// does not throw, does work
std::string& s =boost::get<std::string>(v);
return 0;
}
It's a little arcane and will need some tweaking with variadic arguments to be truly generic, but it does what you want. Someone else needs to figure out if this results in significant code blow-up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With