2009-03-23 13 views
3

私は、フォームの機能を持っている:ブーストラムダコレクションサイズ評価

void DoSomething(const boost::function<bool()>& condition, other stuff); 

この機能は、いくつかの作業を行い、条件が真の場合にのみ返されます。この条件は、異なるコール・サイトで異なる条件を指定したいので、ファンクション・アーギュメントとして表されています。

ここでは直接使用するのはかなり簡単ですが、できるだけ避けることをお勧めしたい、使い捨ての関数や関数オブジェクトをたくさん宣言する必要があります。私はブーストのラムダライブラリを見逃している可能性があることを見てきましたが、私は何か基本的なものが欠けていると思います。私はそれが私が望むことをすることができません。

私は現時点で私を困惑させています。私はstd::vectorというコレクションをdataといいます。私が後にしているのは、そのコレクションのsize()が特定のしきい値に達したときです。基本的には、data.size() >= thresholdのときにconditionファンクタをtrueに戻し、それ以外の場合はfalseにします。しかし、私はラムダ構文でそれを表現するのが難しかった。

(それが動作しませんが、少なくともコンパイルでいる、)私はこれまで思い付くことができましたその最高はこれです:DoSomethingへのエントリ上で

boost::function<bool (size_t)> ge = boost::bind(std::greater_equal<size_t>(), 
               _1, threshold); 
boost::function<size_t()> size = boost::bind(&std::vector<std::string>::size, 
               data); 
DoSomething(boost::lambda::bind(ge, boost::lambda::bind(size)), other stuff); 

、サイズが0であります - 実行中にサイズが大きくなったとしても、condition()への呼び出しは常に0のサイズを持つように見えます(ブーストの内部ではややこしい)が、それぞれgreater_equalを呼び出すように見えます時間condition()が評価された場合は、size()を呼び出すようには見えません。

どのような基本的なことを完全に台無しにしましたか?この種のことを表現する簡単な方法はありますか(できるだけコードをインラインにしておきます)。

私は、理想的にはC#の同等のコード流暢にできるだけ近い、それを取得したいのですが:

DoSomething(delegate() { return data.size() >= threshold; }, other stuff); 
DoSomething(() => (data.size() >= threshold), other stuff); 

答えて

5

問題は、ラムダ関数はdataベクトルではなく、参照のコピーを格納していること、です。そのため、修正中の元のオブジェクトではなく、size()がコピーで呼び出されます。これは、boost::refdataを包むことで解決、代わりに参照を格納することができます。

boost::function<size_t()> size = boost::bind(&std::vector<std::string>::size, 
               boost::ref(data)); 

あなたはまた、あなたのラムダ関数の定義における代わりstd::greater_equal<>の正常な>=演算子を使用し、すべて一緒にそれを組み合わせることができます。

boost::function<bool()> cond = 
    (boost::bind(&std::vector<std::string>::size, boost::ref(data)) 
     >= threshold); 

DoSomething(cond, other stuff); 
+0

ありがとうございました。私には驚くべきことですが、バインドされた関数にそのように> =を適用することができます - 特にラムダバインドでさえないので! :) – Miral

+0

> =は関数オブジェクトのためにオーバーロードされていますが、おそらくboost :: lambda :: bindはもっと良い選択になります... – sth