43

私が理解しているように、すべてのタイプのboost.variantは実際のタイプに解析されます (つまり、ブーストvariant<int, string> a; a="bla-bla"がコンパイル後に に変わるstring a; a="bla-bla"かのように)。

私が試したこと:

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

4 に答える 4

37

v.which()現在保持されているオブジェクトのタイプの 0 から始まるインデックスを返します。

オブジェクトを取得する場合、(関数テンプレートを満たすためにget<T>) コードで静的型を使用して、(効果的に) 動的に型指定されたオブジェクトを参照する必要があります。

タイプをテストし (which()またはをtype()使用)、それに応じて分岐するか、静的ビジターを使用する必要があります。どちらの方法を選択しても、取得する静的型を明示的に指定する必要があり、動的型と一致する必要があります。そうしないと、例外がスローされます。

この問題を回避する 1 つの方法は、バリアント型を直接使用する代わりに、バリアント型を内部に含むクラスを使用し、オブジェクトを使用するために必要な暗黙の変換演算子を最小限の手間で定義することです。

この手法を使用するDynamic C++というプロジェクトがあります。

于 2011-12-01T18:32:28.973 に答える
19

boost.variantRTTI を有効にしている場合、アクティブな型の 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;
于 2011-12-01T16:05:00.300 に答える
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);
}
于 2013-11-12T18:21:57.513 に答える