2

有人可以告诉我如何使用 boost::phoenix lambda 实现以下等效项吗?我知道我可以通过许多其他方式实现它,但我正在尝试学习 Phoenix lambda 表达式,到目前为止,我在这个示例中的所有尝试都失败了。

我想要做的是使用 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());

我发现的大多数 lambda 示例都非常简单,并且不涉及在 lambda 参数对象上调用成员函数,尤其是在存在多个间接级别时。即 _1 应该代表集合的迭代器,它通过用“->”取消引用返回 value_type(是weak_ptr),我想在其上调用过期。但是由于 _1 实际上不是直接的迭代器而是“phoenix::actor”,所以我的取消引用不会编译。

提前感谢所有创意投入。

加布

4

2 回答 2

5

Boost.Phoenix 和之前的 Boost.Lambda 擅长某些任务,但不擅长其他任务。它实际上不起作用的其他之一是与直接按名称调用函数有关。

可以为重载运算符快速轻松地创建 Boost.Phoenix lambda。但是如果你需要一个函数名,那么你必须使用丑陋的语法:

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

这就是你的 lambda 的样子。您可以使用一些using指令来裁剪命名空间,但这最终会是它的样子。在这一点上使用它真的没有什么不同boost::bind

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

Boost.Phoenix 和之前的 Boost.Lambda 最适合用于使用重载运算符或显式定义的 Phoenix 操作对象的 lambda 表达式。如果你只有一个普通的旧函数或成员函数,你必须绑定它来调用它。所以你不妨只使用boost::bind.

于 2011-09-22T06:17:46.993 回答
2

Boost phoenix(和 boost lambda)不支持 -> 运算符。您可以使用“指向成员的指针”运算符 (->*) 作为合理的替代方案。

我发现在使用 lambda 表达式的行之前将成员指针定义为单独的变量很有用:

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 回答