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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8344080/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:24:24  来源:igfitidea点击:

Boost Variant: how to get currently held type?

c++boostboost-variant

提问by myWallJSON

As I understood all types of boost.variantare parsed into real types (meaning as if boost variant<int, string> a; a="bla-bla"would after compilation turn into string a; a="bla-bla") And so I wonder: how to get what type was put into boost variant?

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

What have I tried:

我试过什么:

#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;
}

回答by Ferruccio

v.which()will return the 0-based index of the type of the object currently held.

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

When you are retrieving the object your code must use a static type (in order to satisfy the get<T>function template) to refer to an (effectively) dynamically typed object.

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

You need to either test for the type (using which()or type()) and branch accordingly or use a static visitor. No matter which way you choose, you have to explicitly state the static type that you want to retrieve and it has to match the dynamic type or an exception will be thrown.

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

One way around this problem is instead of using a variant type directly, use a class which contains a variant type internally and then defines any implicit conversion operators necessary to use the object with minimum fuss.

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

I have a project called Dynamic C++which uses this technique.

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

回答by kennytm

boost.varianthas a .type()functionwhich can return the typeid of the active type, provided you've enabled RTTI.

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

You could also define a static visitor to perform actions depending on the type of content of the variant, e.g.

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

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;

回答by richardr

You can use the following that both result in std::type_info objects:

您可以使用以下都导致 std::type_info 对象的内容:

  • the type() member function of boost::variant,
  • the C++ operator typeid() that can be applied to any type or typed expression,
  • boost::variant 的 type() 成员函数,
  • 可以应用于任何类型或类型表达式的 C++ 运算符 typeid(),

together with the member function std::type_info::operator==, to check which type the boost::variant is currently storing. For example,

与成员函数 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);
}