2012-11-10 2 views
6

私が理解できない以下のコードで動作を見ています。boost :: variant - テンプレートパラメータがconst文字列パラメータよりも優先順位が高い理由

bool operator()(T other) const 
bool operator()(const T &other) const 

プログラムの出力は次のとおりです:ポイントは、私は、次のいずれかのようなoperator()の2番目のオーバーロードを宣言した場合ということです

文字列

しかし、私は次のように使用している場合宣言:

bool operator()(T &other) const 

出力は

他のタイプ

operator()(const string &other)は、後者の場合には呼び出されていない理由を誰かが説明していただけますか?

#include "boost/variant/variant.hpp" 
#include "boost/variant/apply_visitor.hpp" 

using namespace std; 
using namespace boost; 

typedef variant<string, int> MyVariant; 


class StartsWith 
    : public boost::static_visitor<bool> 
{ 
public: 
    string mPrefix; 
    bool operator()(const string &other) const 
    { 
     cout << "string" << endl; 
     return other.compare(0, mPrefix.length(), mPrefix) == 0; 
    } 
    template<typename T> 
    bool operator()(T &other) const 
    { 
     cout << "other type" << endl; 
     return false; 
    } 
    StartsWith(string const& prefix):mPrefix(prefix){} 
}; 

int main(int argc, char **argv) 
{ 
    MyVariant v(string("123456")); 
    apply_visitor(StartsWith("123"), v); 
    return 0; 
} 

答えて

5

ここにはconstの問題があります。

constオブジェクトではなくapply_visitorに渡しています。constオブジェクトのメンバーは適用されないビジターに渡されません。あなたのケースではstring& - 文字列型への参照です。このテンプレートは完全一致です:

template<typename T> 
bool operator()(T &other) const 

これが選択されています。この機能は、完全一致ではありません - それはスキップされます。もちろん

bool operator()(const string &other) const 

をあなたはその演算子を提供する場合:

bool operator()(string &other) const 

非テンプレート関数がテンプレート1の前に考えられているので、それは、選択されることになります。

だから、ソリューションです:文字列参照(定数ではない)を取り、あなたの訪問者のメソッドを提供どちらか - ...または適用するのconstバリアントを渡す

まずソリューション - 文字列のオペレータからのconstを削除します。

bool operator()(/*const*/ string &other) const 
//    ^^^^^^^^^ remove it 

: - 一般の訪問者へのconst指定子を追加

const MyVariant& cv = v; 
apply_visitor(StartsWith("123"), cv); 
//        ^^ const object passed here 

第三ソリューション: -

第二の溶液constオブジェクトを渡します

template<typename T> 
bool operator()(const T &other) const 
//    ^^^^^ 

ソリューション第1位と第3位が第2位より優れています。一貫性のあるビジターをバリアントに渡す必要があります。コンパイラは適切な関数を選択する必要があります。

+0

タイプフリークとして、私は、**第3の解決策は**最高の**と言いたいと思います。** const-correct **。パラメータを変更しない場合は、非const参照によってパラメータを取得する必要はありません。 @MatthieuM。 –

+0

。この場合、あなたは正しいです。私は 'T &&'について言及していませんでした。おそらくそれがベストでしょうが、 'T &&'と 'const T&'の違いについて議論しているところがたくさんあります。 – PiotrNycz

関連する問題