繁体   English   中英

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

[英]Boost Variant: how to get currently held type?

据我了解,所有类型的boost.variant都被解析为真实类型(意思是好像 boost 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;
}

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

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

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

解决这个问题的一种方法是不直接使用变体类型,而是使用一个在内部包含变体类型的类,然后定义任何必要的隐式转换运算符,以便以最小的麻烦使用该对象。

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

boost.variant有一个.type()函数,它可以返回活动类型的 typeid,前提是您已启用 RTTI。

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

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;

您可以使用以下都导致 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);
}

您可以使用boost::get的指针版本。 教程有这个例子:

void times_two( boost::variant< int, std::string > & operand )
{
    if ( int* pi = boost::get<int>( &operand ) )
        *pi *= 2;
    else if ( std::string* pstr = boost::get<std::string>( &operand ) )
        *pstr += *pstr;
}

因此,您可以像通常使用boost::get一样使用它,但将指针传递给变体,结果是一个指针,如果该指针不是当前存储在变体中的类型,则该指针为nullptr 如果该类型在变体的类型列表中出现不止一次,则没有用,但这并不常见。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM