2

誰かがboost::phoenixラムダを使用して次の同等のものを実装する方法を教えてもらえますか?他の多くの方法で実装できることはわかっていますが、Phoenixラムダ式を学習しようとしていますが、これまでのところ、この例でのすべての試みは失敗しました。

私がやりたいのは、std :: remove_ifを使用して、weak_ptrsのセットを反復処理し、期限切れのものを削除することです。

したがって、コードは次のようになります。

typedef std::set<weak_ptr<Xyz>> XyzWptrSetType;
...
XyzWptrSetType   xyzWptrSet;
...
XyzWptrSetType::iterator it =
    std::remove_if(xyzWptrSet.begin(), xyzWptrSet.end(),
                   (boost::phoenix::arg_names::_1->expied()));  
// the lambda part DOESN'T compile in previous line
std::erase(it, xyzWptrSet.end());

私が見つけたラムダの例のほとんどは非常に単純であり、特に複数のレベルの間接参照がある場合に、ラムダ引数オブジェクトでメンバー関数を呼び出すことを扱いません。つまり、_1は、「->」で逆参照することにより、expiredと呼びたいvalue_type(weak_ptrである)を返すセットのイテレータを表すことが期待されます。しかし、_1は実際に直接反復子ではなく、「フェニックス::アクター」であるため、間接参照はコンパイルされません。

事前にすべての創造的な入力をありがとう。

ガベ

4

2 に答える 2

5

Boost.Phoenixとその前のBoost.Lambdaは、特定のタスクには優れていますが、他のタスクには優れていません。それが実際には機能しない他の1つは、名前で関数を直接呼び出すことと関係があります。

Boost.Phoenixラムダは、オーバーロードされた演算子用にすばやく簡単に作成できます。ただし、関数名が必要な場合は、醜い構文を使用する必要があります。

boost::phoenix::bind(&boost::weak_ptr::expired, boost::phoenix::arg_names::_1)

それがあなたのラムダがどのように見えるかです。usingいくつかのディレクティブを使用して名前空間を切り取ることができますが、最終的にはそのようになります。boost::bindこの時点で使用するのと実際には違いはありません。

boost::bind(&boost::weak_ptr::expired, _1)

Boost.Phoenixとその前のBoost.Lambdaは、オーバーロードされた演算子、または明示的に定義されたフェニックスアクションオブジェクトを使用するラムダ式に最適です。単純な古い関数またはメンバー関数がある場合は、それをバインドして呼び出す必要があります。したがって、を使用することもできますboost::bind

于 2011-09-22T06:17:46.993 に答える
2

ブーストフェニックス(およびブーストラダム)は->演算子をサポートしていません。妥当な代替手段として、「メンバーへのポインター」演算子(-> *)を使用できます。

ラムダ式を使用する行の直前に、メンバーポインターを個別の変数として定義すると便利です。

bool (weak_ptr<Xyz>::*expired)()const = &weak_ptr<Xyz>::expired ;
XyzWptrSetType::iterator it =
    std::remove_if(xyzWptrSet.begin(), xyzWptrSet.end(), (&_1->*expired)() );

他の人が指摘しているように、あなたのような状況ではbind()を検討する価値もあります。

于 2011-09-22T08:46:31.040 に答える