我曾尝试为boost::variant
编写一个vistor来获取类型的参数包,并为每种类型生成operator()
。当调用正确的函数时,我仍然在尝试从变量中的访问者保存get-ed对象时出错。
我的访客是这样的:
#include <boost/variant.hpp>
#include <iostream>
template <class T>
class GenericGettorSpecialization
{
public:
const T& operator()(T& t)
{
std::cout << typeid(T).name() << "\n";
return t;
}
};
template <class...>
class GenericGettorSpecializationDriver;
template <>
class GenericGettorSpecializationDriver<>
{
public:
struct dummy
{
};
const dummy& operator()(const dummy&);
};
template <class Head, class... Tail>
class GenericGettorSpecializationDriver<Head, Tail...>
: protected GenericGettorSpecializationDriver<Tail...>,
protected GenericGettorSpecialization<Head>
{
public:
using GenericGettorSpecializationDriver<Tail...>::operator();
using GenericGettorSpecialization<Head>::operator();
};
template <class Head, class... Tail>
struct GenericGettor
: boost::static_visitor<>,
protected GenericGettorSpecializationDriver<Head, Tail...>
{
public:
using GenericGettorSpecializationDriver<Head, Tail...>::operator();
};
正如您在调用运算符中放置std::cout << typeid(T).name() << "\n";
时的调试目的所见。
现在我测试了它:
int
main()
{
boost::variant<std::string, int, double> v;
GenericGettor<std::string, int, double> g;
v = "some string";
boost::apply_visitor(g, v); // prints "NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"
v = 10;
boost::apply_visitor(g, v); // prints "i"
v = 7.3;
boost::apply_visitor(g, v); // prints "d"
auto x = boost::apply_visitor(g, v); // throws compile time error "error: variable has incomplete type 'void'"
}
显然boost::apply_vistor
会返回void
,但是如何从variant
中获取引用?
答案 0 :(得分:0)
这种吸气剂已经存在:boost::get<> function template。
但是,请记住,变体内容是在运行时设置的,所以在编译时中完全不可能知道它。
这就是为什么你应该告诉get
函数模板你希望它返回什么类型 - 如果变量在那个时间点不包含它,它将抛出异常。
或者,您可以使用variant::which()
成员函数,它返回当前类型的索引 - 这也是运行时值。