boost :: variant gettor-visitor:保存返回的引用

时间:2017-02-24 14:21:11

标签: c++ boost visitor boost-variant

我曾尝试为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中获取引用?

1 个答案:

答案 0 :(得分:0)

这种吸气剂已经存在:boost::get<> function template

但是,请记住,变体内容是在运行时设置的,所以在编译时中完全不可能知道它。

这就是为什么你应该告诉get函数模板你希望它返回什么类型 - 如果变量在那个时间点不包含它,它将抛出异常。

或者,您可以使用variant::which()成员函数,它返回当前类型的索引 - 这也是运行时值。