2017-02-24 10 views
1

タイプのパラメータパックを取り、タイプごとにoperator()を生成するboost::variantのためのビスタを作成しようとしました。正しい関数が呼び出されている間も、変数から訪問者のget-edオブジェクトを保存しようとするとエラーが表示されます。boost :: variant gettor-visitor:返された参照を保存する

マイビジターこれです:あなたが呼び出し演算子に入れstd::cout << typeid(T).name() << "\n";でデバッグの目的のために見ることができるように

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

今、私はこのようにそれをテストした:

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

すべての変数は、コンパイル時に明確な型を持たなければなりません。任意の実行点におけるバリアントの内容は、実行時まで知られていません。バリアントからオブジェクトを抽出する場合(実行時にタイプが一致しない場合は例外が発生します)、['boost :: get'](http://www.boost.org/doc/libs/)を使用してください1_61_0/doc/html/boost/get_idp74804384.html)。 – Quentin

+0

しかし、バリアントが現在保持しているタイプがわからない場合はどうすればよいですか?ブースの文書では、このような状況ではビジターが関心を持っていますが、ビジターが何かを得るためにビジターを利用するのではなく、むしろそのバリアントの価値を操作します。http://www.boost.org/doc/libs/1_61_0/ doc/html/variant/tutorial.html#variant.tutorial.basic –

+1

はい、そうです。ビジターは、可能なタイプごとに1つのオーバーロードを含み、 'apply_visitor'は正しいタイプを呼び出します。それ以来、あなたは過負荷の内部の静的なタイプを知っていますが、バブルアップすることはできません。特定の静的型を取得する場合は、 'get'が必要です。これらの2つのツールを使ってプログラムを実装する方法は、あなたがそれらのプログラムで何をしたいかによって異なります。 – Quentin

答えて

0

このようなゲッターは既に存在します:boost::get<> function template

ただし、バリアントの内容は実行時に設定されていることを心に留めておくので、コンパイル時でそれを知ることは絶対に不可能です。

get関数テンプレートに返すタイプを指定する必要があります。その時点でバリアントにそれが含まれていない場合、例外がスローされます。

また、variant::which()メンバ関数を使用することもできます。この関数は、現在の型(実行時の値)のインデックスを返します。

関連する問題