2009-07-08 9 views
2

これをどのようにしてコンパイルできますか?エラーは私がboost :: ref()を使う時です。 boost :: refはC++アルゴリズムクラスへの参照を渡すために使われていると思いますか?人々が提案されているようBoost :: refを正しく使用しています..?

list<Object> lst; 
    lst.push_back(Object(1,2.0f)); 
    lst.push_back(Object(3,4.3f)); 

    struct between_1_and_10 
    { 
    int d; 
    void operator() (Object& value) 
    { 
     value.a += 5; value.b -= 3.3f; 
     cout << d << endl; 
     d += value.a; 
    } 
    }; 

    between_1_and_10 val; 
    val.d = 4; 
    for_each(lst.begin(), lst.end(), boost::ref(val)); // Problem is here 
    printf("rg"); 

EDITは、ここでコンパイラエラーです:

1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\algorithm(29) : error C2064: term does not evaluate to a function taking 1 arguments 
1>  c:\users\swangrun\desktop\minescout work\feat-000-gettargetimages\minescouttest\maintest.cpp(102) : see reference to function template instantiation '_Fn1 std::for_each<std::list<_Ty>::_Iterator<_Secure_validation>,boost::reference_wrapper<T>>(_InIt,_InIt,_Fn1)' being compiled 
1>  with 
1>  [ 
1>   _Fn1=boost::reference_wrapper<main::between_1_and_10>, 
1>   _Ty=Object, 
1>   _Secure_validation=true, 
1>   T=main::between_1_and_10, 
1>   _InIt=std::list<Object>::_Iterator<true> 
1>  ] 
+0

for_each()行にあるはずです。しかし、何が問題なのですか?エラーを再現できるだけのエラーまたは十分なコードを提供する必要があります。 –

+0

問題はコンパイルされないということです。私は答えを受け入れました、あなたの参加に感謝! – sivabudh

+0

Martinが意味することは、「エラーメッセージのテキストをコピーして質問に貼り付ける」ことです。そうすれば、コンパイラが何を言っているかを説明することができます。おそらく、エラーを見つけるために必要なすべての情報が得られたはずです。少なくとも、コンパイラエラーのテキストを検索する他の人が質問とその答えを見つけることができるように、これを行う必要があります。 –

答えて

7

このあなたが本当に欲しいもの:

for_each(lst.begin(), lst.end(), boost::bind<void>(boost::ref(val),_1 )); 

EDIT:OPの要求に応じていくつかの説明。 for_each()は関数を取りますが、単に構造体への参照を渡しているだけです(構造体には演算子()がオーバーロードされていますが、渡していません)。 bind()は基本的に構造体内の関数を "公開"します。

EDIT2:「_1」の説明は、下記のコメントにあります。

+0

ありがとうございます。まさに私が探していたもの。あまりに面倒でないなら、バインドが必要な理由を詳しく教えてもらえますか?その面白いものは何ですか?申し訳ありません、私はBoostを初めて使っています。 (当然のことながら、ちょうど使用したテクニックのどこかに良いチュートリアルがあります)。 – sivabudh

+1

コンパイラがboost:refでラップされた関数の戻り値の型を推論できなかったため、おそらくバインドが必要です。 "_1"については、こちらをご覧ください:http://www.boost.org/doc/libs/1_39_0/libs/bind/bind.html#with_functions –

+0

-1、_1はラムダプレースホルダーです。これは、実際には、for_eachのイテレータが指す "現在の"アイテムを表します。 – paxos1977

-1

はブースト:: refをせずにそれを試してみてください。

12

boost::reference_wrapper(これはboost::refが返します)operator()をオーバーロードしません。あなたはboost::bindでそれを使用することができます。特別な扱いがあります(refを使用しないと、bindは提供された関数オブジェクトをコピーします)。

しかし、for_eachは、そのオブジェクトを呼び出す関数オブジェクトを返します。だからこの

between_1_and_10 val; 
val.d = 4; 
val = for_each(lst.begin(), lst.end(), val); 
printf("rg"); 

それはコピーval上のものを呼び出して、それが最後の呼び出しの後だとして関数オブジェクトを返しますか。


あなたがそれを誤用するように見えるので、あなたが、boost::refを使用する可能性がありますどこちょうどあなたを伝えるために。値によって、そのパラメータを取り、別の関数を呼び出すテンプレートを想像:

void g(int &i) { i++; } 

template<typename T> 
void run_g(T t) { g(t); } 

あなたが今変数とそれを呼び出したい場合は、それをコピーします。これは妥当な決定です。たとえば、データをスレッドに開始パラメータとして渡す場合は、ローカル関数からスレッドオブジェクトにコピーすることができます。しかし時には、それをコピーしないで、実際に参照を渡すこともできます。ここではboost::reference_wrapperが役に立ちます。実際には、次のことは、我々が何を期待し、出力1:結合引数の

int main() { 
    int n = 0; 
    run_g(boost::ref(n)); 
    std::cout << n << std::endl; 
} 

は、コピーが良いデフォルトです。また、配列や関数をポインタに崩壊させることもできます(参照によって受け入れるとTはおそらく配列/関数型になり、いくつかの厄介な問題を引き起こすでしょう)。