2016-03-31 6 views
1

私はstd::arrayboost::variantオブジェクトを持っていて、私はboost::static_visitorを作成しようとしています。バリアントメンバータイプ。それはそうここに私の実装を模倣するコードスニペットですが、一口です:boost :: variant訪問者の返信エラー

#include <boost/variant.hpp> 
#include <array> 

struct SomeType {}; 

struct A { 
    SomeType something; 
    SomeType& someMethod() { return something; } 
}; 

struct B { 
    SomeType something; 
    SomeType& someMethod() { return something; } 
}; 

struct C { 
    SomeType something; 
    SomeType& someMethod() { return something; } 
}; 

typedef boost::variant<A, B, C> MyVariant; 

class SomeVisitor : public boost::static_visitor<> { 
public: 
    template<typename T> 
    SomeType& operator()(T& operand) const { 
    return operand.someMethod(); 
    } 
}; 

class MyVariants { 
public: 
    SomeType* getSomething(unsigned index); 

private: 
    static const size_t count = 100; 
    std::array<MyVariant, count> variants_; 
}; 

SomeType* MyVariants::getSomething(unsigned index) { 
    if(index < count) { 
    MyVariant& variant = variants_[index]; 
    SomeType& something = boost::apply_visitor(SomeVisitor(), variant); 
    return &something; 
    } 
    else { 
    return nullptr; 
    } 
} 

このスニペットは打ち鳴らす3.6.2でコンパイルしますが、GCC 5.3.1は、次のことを吐き出す(ブーストバリアントヘッダから数十エラーが続きます)

test.cpp:43:47: error: invalid initialization of non-const reference of type 'SomeType&' from an rvalue of type 'boost::static_visitor<>::result_type {aka void}' 
    SomeType& something = boost::apply_visitor(SomeVisitor(), variant); 

すべてのエラーは、同じことを言っているように見える - 訪問者の戻り値の型はvoidある、と私はSomeType&にそれをバインドすることはできません。私はSomeVisitorの実装で構文エラーがあるとは思わないが、これはclangでうまくコンパイルされるからだ。

This questionおよびthis questionは、boost::static_visitorによって生成された同様のエラーを示し、両方ともC++の最も厄介な解析によって説明されました。両方のこれらの質問には、問題はこのようなもの(上記の私のスニペットから型を使用して)であった。このような状況において

MyVariant variant(A()); 
SomeType& something = boost::apply_visitor(SomeVisitor(), variant); 

を、私は最も厄介な解析が適用されるかを理解することができます。 MyVariant variant(A());はコンパイラにとってあいまいかもしれません。 MyVariant& variant = variants_[index]がかなり明白に見えるので、私はこれが私のスニペットにどのように当てはまるのかわかりません。これらの質問が私の問題に関連しているのかどうかはわかりません。 /ヘルプ

何かアドバイスは答えとして提供

+2

あなたがstatic_visitorのテンプレート引数リストに戻り値の型を指定する必要があります。それを空にしておくと、functorがvoidを返すことをコンパイラに伝えることになります。 –

+0

ありがとう!それがまさに問題でした。私は(右の構文で)数週間前に、戻り値を持つ 'ブースト:: static_visitor'を作ったので、私は、我々はすべてそれをやった –

+0

二重に恥ずかしいです。 C++ 14以降のバージョンのブーストでは、静的な訪問者は必要ありません。 'auto&'引数型のラムダで十分です。 –

答えて

1

コメントをいただければ幸いです。

あなたがstatic_visitorのテンプレート引数リストの戻り値の型を指定する必要があります。それを空にしておくと、functorがvoidを返すことをコンパイラに伝えることになります。

class SomeVisitor : public boost::static_visitor<SomeType&> { 
public: 
    template<typename T> 
    SomeType& operator()(T& operand) const { 
    return operand.someMethod(); 
    } 
}; 

また、C++ 14とブーストのそれ以降のバージョンで:

auto& something = boost::apply_visitor([](auto& x) { return x.someMethod(); }, 
             variant); 
関連する問題