2012-03-15 7 views
3

私は、次のコードを持っている:C2780コンパイルエラーのトンでMSVC9 SP1結果にコンパイル使用してブースト::バインドはコンパイルに失敗し

int MimeDocument::GetAttachmentId(std::string const& content_id) 
{ 
    using namespace boost::lambda; 
    using boost::lambda::_1; 
    using boost::bind; 

    int id = 0; 

    std::vector<std::string>::iterator it = 
     std::find_if(attachment_list_.begin(), attachment_list_.end(), 
      bind(&std::string::find, content_id, _1) != std::string::npos 
     ); 

    if(it != attachment_list_.end()) { 
     id = std::distance(attachment_list_.begin(), it); 
    } 

    return id; 
} 

1>c:\code\work\cmake-mds\server\gmmserver\domino\server\interface\dimime.cpp(210) : error C2780: 'boost::_bi::bind_t<_bi::dm_result<MT::* ,A1>::type,boost::_mfi::dm<M,T>,_bi::list_av_1<A1>::type> boost::bind(M T::* ,A1)' : expects 2 arguments - 3 provided 
1>  c:\code\work\cmake-mds\build-vc9\third_party\boost\1.48.0\include\boost\bind\bind.hpp(1728) : see declaration of 'boost::bind' 
1>c:\code\work\cmake-mds\server\gmmserver\domino\server\interface\dimime.cpp(210) : error C2780: 'boost::_bi::bind_t<Rt2,boost::_mfi::cmf8<R,T,B1,B2,B3,B4,B5,B6,B7,B8>,_bi::list_av_9<A1,A2,A3,A4,A5,A6,A7,A8,A9>::type> boost::bind(boost::type<T>,R (__thiscall T::*)(B1,B2,B3,B4,B5,B6,B7,B8) const,A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 11 arguments - 3 provided 
1>  c:\code\work\cmake-mds\build-vc9\third_party\boost\1.48.0\include\boost\bind\bind_mf2_cc.hpp(223) : see declaration of 'boost::bind' 
1>c:\code\work\cmake-mds\server\gmmserver\domino\server\interface\dimime.cpp(210) : error C2780: 'boost::_bi::bind_t<Rt2,boost::_mfi::mf8<R,T,B1,B2,B3,B4,B5,B6,B7,B8>,_bi::list_av_9<A1,A2,A3,A4,A5,A6,A7,A8,A9>::type> boost::bind(boost::type<T>,R (__thiscall T::*)(B1,B2,B3,B4,B5,B6,B7,B8),A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 11 arguments - 3 provided 
1>  c:\code\work\cmake-mds\build-vc9\third_party\boost\1.48.0\include\boost\bind\bind_mf2_cc.hpp(212) : see declaration of 'boost::bind' 

向上に関連するコンパイルエラーが私に事実上読めないと役に立たないですので、私は誰かが私に何が起こっているかを把握することができます願っています。ここでは、リストの先頭からほんの一部です。前もって感謝します。 bind

+0

標準ライブラリのアドレスを取るを選ぶ(メンバー)関数は、違法です。私は最後の(削除された)質問でなぜこのコメントを無視したのか分かりません。 – ildjarn

+0

@ildjarn 2つの理由:1)あまりにも早く投稿しました。私のコードは駄目で、2)あなたは理由を説明しませんでした(標準などからの引用はありません)。また、あなたのコメントはコンパイラの失敗の理由を扱っていません。違法であっても、理由を知りたいのですが。 –

+2

4つの異なる 'std :: string :: find'があります。コンパイラはどちらを選択する必要がありますか? –

答えて

5

std::string::findの4つのオーバーロードがあります。

size_t find(const string& str, size_t pos = 0) const; 
size_t find(const char* s, size_t pos, size_t n) const; 
size_t find(const char* s, size_t pos = 0) const; 
size_t find(char c, size_t pos = 0) const; 

したがって1は、アドレスがを撮影された特定の多重定義関数を指定することにより、(あいまいさを解決)などを一つ選ぶようにコンパイラを助けなければならない:

boost::bind(static_cast<size_t(std::string::*)(const std::string&, size_t) const>(&std::string::find), content_id, _1, 0) 

むしろ醜いですね。

std::string::find()は、失敗した検索でstd::string::npos(ほとんどの場合はsize_t(-1))を返します。その後、size_t(-1)bool(true)に変換して、std::find_if()が残りの引数が何であっても最初の引数を返すことになります。

std::string::find()の結果をstd::string::nposと比較する必要があります。どちらかあまりにも読める見えない

// ... 

std::vector<std::string>::iterator it = std::find_if(
     attachment_list_.begin() 
    , attachment_list_.end() 
    , boost::bind(
      std::not_equal_to<std::string::size_type>() 
     , std::string::npos 
     , boost::bind(
       static_cast<size_t(std::string::*)(const std::string&, size_t) const>(&std::string::find) 
      , &content_id // pass by pointer, don't copy 
      , _1 
      , 0) 
      ) 
    ); 

boost::bindを使用すると、次のようになりますこと。

それはboost::lambda::bindと小さなもう少し読みやすいことがあります

#include <boost/lambda/bind.hpp> 
#include <boost/lambda/lambda.hpp> 

// ... 

std::vector<std::string>::iterator it = 
    std::find_if(
      attachment_list_.begin() 
     , attachment_list_.end() 
     , boost::lambda::constant(std::string::npos) != boost::lambda::bind(
       static_cast<size_t(std::string::*)(const std::string&, size_t) const>(&std::string::find) 
      , &content_id // pass by pointer, don't copy 
      , boost::lambda::_1 
      , 0 
      ) 
    ); 

それはC++11 lambdaで最も読みやすいとエレガントに見える:

std::vector<std::string>::iterator it = std::find_if(
     attachment_list_.begin() 
    , attachment_list_.end() 
    , [&content_id](std::string const& i) { return std::string::npos != content_id.find(i); } 
    ); 

さらに私はidが失敗した検索で返さが0であることに気づきましたこれは、最初の要素で検索が成功した場合に返される値と同じです。つまり、この関数の呼び出し元は、失敗した検索と、最初の(0番目の)要素が一致したときを区別することができません。呼び出し側は簡単に成功と失敗の検索の間で言うと、必要に応じて、一致指数を見つけることができ、このバージョンを使用して

std::string* MimeDocument::GetAttachmentId(std::string const& content_id) { 
    for( std::vector<std::string>::iterator i(attachment_list_.begin()), j(attachment_list_.end()) 
     ; i != j 
     ; ++i 
     ) { 
     if(std::string::npos != content_id.find(*i)) 
      return &*i; 
    } 
    return NULL; 
} 

ここは、検索のためのプレーンなループを使用することが最も簡単で、ポータブルである

MimeDocument doc; 
// ... populate doc 
if(std::string* found = doc.GetAttachmentId("1")) { 
    // the search was successful. 
    size_t found_index = found - &doc.attachment_list_.front(); 
} 

だから、あなたの毒...

2

パラメータタイプは、任意の方法(直交テンプレートタイプ)で、唯一本体内で相互に関連していないコンパイラはfindの過負荷が必要とされる決定することができます。コンパイラは、何を渡すべきかを把握するために関数宣言を見ることしか許されておらず、あいまいな可能性のあるオーバーロードがfindであり、コンパイラはどちらを使うのかを判断するためにバインドされた引数型を使用できません。

この場合、ネストされた文字列検索を行うために5行のファンクタを書くのが簡単になると思います。

関連する問題