Assume that you have a boost::any object and a boost::variant object.
I\'m looking for a generic function convert, that takes
You can call boost::any_cast for each of the types within boost::variant and stop when the first cast succeeded:
#include
#include
#include
#include
#include
#include
#include
#include
#include
template
struct mpl_sequence_to_std_tuple
{
template
static auto x(std::index_sequence) -> std::tuple::type...>;
using type = decltype(x(std::make_index_sequence::type::value>{}));
};
struct signal_conversion_success{};
template
void try_convert(const boost::any& any, Variant& var)
{
try
{
var = boost::any_cast(any);
throw signal_conversion_success{};
}
catch(const boost::bad_any_cast &)
{
}
}
template
std::string parameter_pack_to_string(const std::string& separator = ", ")
{
std::stringstream ss;
ss << boost::typeindex::type_id().pretty_name();
auto l = {0, (void(ss << separator << boost::typeindex::type_id().pretty_name()),0)...};
std::ignore = l;
return ss.str();
}
template
void do_convert(const boost::any& any, Variant& var, std::tuple)
{
bool success = false;
try {
auto l = {0, (void(try_convert(any, var)), 0)... };
std::ignore = l;
}
catch(const signal_conversion_success&)
{
success = true;
}
if (!success)
{
std::stringstream ss;
ss << "cannot convert this boost::any instance to any of the following types: ";
ss << parameter_pack_to_string();
throw std::invalid_argument(ss.str());
}
}
template
void convert(const boost::any& any, Variant& var)
{
using Tuple = typename mpl_sequence_to_std_tuple::type;
do_convert(any, var, Tuple{});
}
struct print_visitor : public boost::static_visitor
{
template
void operator()(T&& t) const
{
std::cout << boost::typeindex::type_id().pretty_name() << ": " << std::forward(t) << std::endl;
}
};
int main()
{
using Variant = boost::variant;
boost::any any = std::string("Hello World");
Variant var;
convert(any, var);
boost::apply_visitor(print_visitor(), var);
}
live example
In case none of the casts succeeded, an exception is thrown, see the following live example.