我在boost::variant
整个项目中使用不同的类型。例如我有
typedef boost::variant<A1, A2> TA;
typedef boost::variant<B1, B2, B3> TB;
typedef boost::variant<A1, B2> TC;
为了boost::variant
通过统一的接口传输这些不同的类型,我正在使用boost::any
. 例如:
TA a=A1();
boost::any container=a;
现在A1
从这种情况下提取数据container
变得有点乏味。我必须明确写
A1 a=boost::get<A1>(boost::any_cast<TA>(container));
我只是想知道,是否有可能实现这样的模板辅助函数:
template<typename T>
T getValue<T>(const boost::any& any) {
auto var=boost::any_cast</* What to put here*/>(container);
return boost::get<T>(var);
}
但是在这里我真的很困惑要写入什么类型boost::any_cast
。
部分解决方案:
在重构了我上一个问题的答案的代码后,我能够得出以下问题的部分解决方案。
不幸的是,该解决方案仍有两个严重的缺陷。
首先,我不知道如何排除所有不能包含请求的类型boost::variant
的 s 。Variants
T
其次,我必须明确提及我可能的boost::variant
类型列表。我认为这个限制不像第一个那么严格。
#include <boost/variant.hpp>
#include <boost/any.hpp>
#include <boost/optional.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/remove_if.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/joint_view.hpp>
#include <vector>
#include <iostream>
template<class T, class V>
struct variantToType
{
variantToType(const V& value) : value(value) { }
boost::optional<T> result;
V value;
void operator()(const T& t)
{
if (T* val = boost::get<T>(&value)) {
result = boost::make_optional<T>(*val);
} else {
result = boost::none;
}
}
};
template<typename T>
struct anyToVariant {
anyToVariant(const boost::any& value) : value(value) { }
boost::optional<T> result;
const boost::any value;
template<typename VARIANT>
void operator()(const VARIANT&) {
try {
VARIANT var=boost::any_cast<VARIANT>(value);
variantToType<T, VARIANT> generator(var);
boost::mpl::for_each<VARIANT::types>(boost::ref(generator));
if (generator.result) {
result = generator.result;
}
}
catch (const boost::bad_any_cast&) {}
}
};
template<class T>
boost::optional<T> convert(const boost::any&value) {
using namespace boost;
anyToVariant<T> x(value);
//using AllTypes = boost::mpl::joint_view<V1::types, V2::types>; // Of no help?
using Variants = mpl::vector<V1, V2>::type;
mpl::for_each<Variants>(boost::ref(x));
return x.result;
}
typedef boost::variant<int> V1;
typedef boost::variant<double, int> V2;
int main(int argc, char**args) {
try {
{
V1 x = 5;
boost::any any = x;
boost::optional<int> y = convert<int>(any);
std::cout << y.value() << std::endl;
}
{
V2 x = 5.5;
boost::any any = x;
// This will not compile due to boost::get, as V1 does not contain a double type. :-(
// boost::optional<double> y = convert<double>(any);
// std::cout << y.value() << std::endl;
}
}
catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}