Boost Variant:如何获得当前持有的类型?

myW*_*SON 41 c++ boost boost-variant

据我所知,所有类型的boost.variant都被解析成真实的类型(意思是variant<int, string> a; a="bla-bla"在编译之后就好像是转换string a; a="bla-bla")所以我想知道:如何获得什么类型被放入boost变体?

我试过了什么:

#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>

int main()
{
    typedef boost::function<double (double x)> func0;
    typedef boost::function<double (double x, double y)> func1;
    typedef boost::variant<int, func0, func1> variant_func;
    func1 fn = std::plus<double>();
    variant_func v(fn);
    std::cout << boost::get<func1>(v)(1.0, 1.0) << std::endl; // this works
    //std::cout << boost::get<v::type>(v)(1.0, 1.0) << std::endl; // this does not compile with many errors
    // std::cout << (v)(1.0, 1.0) << std::endl; // this fails with Error    1   error C2064: term does not evaluate to a function taking 2 arguments

    std::cin.get();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Fer*_*cio 33

v.which() 将返回当前持有的对象类型的从0开始的索引.

当您检索对象时,您的代码必须使用静态类型(为了满足get<T>函数模板)来引用(有效)动态类型的对象.

您需要测试类型(使用which()type())并相应地进行分支或使用静态访问者.无论选择哪种方式,都必须显式声明要检索的静态类型,并且必须与动态类型匹配,否则将抛出异常.

绕过这个问题的一种方法是不使用直接使用变量类型,而是在内部使用包含变量类型的类,然后定义使用该对象所需的任何隐式转换运算符.

我有一个名为Dynamic C++的项目,它使用这种技术.

  • 动态C++的+1,这不是我的事,但我看了一眼,看起来很干净.做得好! (2认同)

ken*_*ytm 18

boost.variant如果已启用RTTI,则具有可以返回活动类型的typeid的.type()函数.

您还可以定义静态访问者以根据变体内容的类型执行操作,例如

struct SomeVisitor : public boost::static_visitor<double>
{
    double operator()(const func0& f0) const { return f0(1.0); }
    double operator()(const func1& f1) const { return f1(1.0, 1.0); }
    double operator()(int integer) const { return integer; }
};
...
std::cout << boost::apply_visitor(SomeVisitor(), v) << std::endl;
Run Code Online (Sandbox Code Playgroud)


ric*_*rdr 11

您可以使用以下两者导致std :: type_info对象:

  • boost :: variant的type()成员函数,
  • 可以应用于任何类型或类型表达式的C++运算符typeid(),

与成员函数std :: type_info :: operator ==一起检查boost :: variant当前存储的类型.例如,

boost::variant<int, bool, std::string> container;
container = "Hello world";

if (container.type() == typeid(std::string)) {
    std::cout << "Found a string: " << boost::get<std::string>(container);
}
else if (container.type() == typeid(int)) {
    std::cout << "Found an int: " << boost::get<int>(container);
}
Run Code Online (Sandbox Code Playgroud)

  • 我尝试在MSVS 2013上使用`boost :: variant <vector <int>,int>`并且它有效.您尝试使用哪种编译器?你能解释一下你认为它不适用于某些情况的原因吗? (8认同)