3

私は次の形式の関数を持っています:

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

この関数はいくつかの作業を行い、条件が真の場合にのみ戻ります。コールサイトごとに異なる条件を提供したいので、条件はファンクター引数として表現されています。

さて、これを直接使用するのはかなり簡単ですが、多くの小さな使い捨て関数またはファンクターオブジェクトを宣言する必要があります。これは、可能であれば避けたいと思います。私はこれらをなくすための可能な方法についてBoostのラムダライブラリを調べてきましたが、基本的なものが欠けていると思います。やりたいことができない。

現時点で私を困惑させている1つのケース:私は;std::vectorと呼ばれるコレクションを持っています。data私が求めているのはsize()、そのコレクションのが特定のしきい値に達したときです。基本的に、conditionファンクターがtrueを返し、それ以外のdata.size() >= threshold場合はfalseを返すようにします。しかし、ラムダ構文でそれを表現するのに苦労しています。

私がこれまでに思いついた最高のもの(少なくともコンパイルされますが、動作しません)は次のとおりです。

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);

に入るとDoSomething、サイズは0になります。実行中にサイズが大きくなっても、呼び出しはcondition()常にサイズが0になるように見えます。これをトレースすると(Boostの内部では少し注意が必要です)、評価されるgreater_equalたびに呼び出しているように見えますが、呼び出してcondition()いるようには見えませんsize()

それで、私が完全に台無しにした基本的なことは何ですか?この種のことを表現するためのより簡単な方法はありますか(コードを可能な限りインラインに保ちながら)?

理想的には、C#と同等のコードの流暢さにできるだけ近づけたいと思います。

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

1 に答える 1

5

問題は、ラムダ関数がdata参照ではなくベクトルのコピーを格納することです。Sosize()は、変更している元のオブジェクトではなく、コピーに対して呼び出されます。これは、代わりに参照を格納する でラップすることで解決できますdataboost::ref

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);
于 2009-03-23T07:21:04.027 に答える