3

我有一个形式的功能:

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

这个函数做一些工作并且只在条件为真时返回。该条件已表示为函子参数,因为我想在不同的调用站点提供不同的条件。

现在,直接使用它相当简单,但它需要声明许多小的一次性函数或仿函数对象,如果可能的话,我想避免这些。我一直在研究 Boost 的 lambda 库,以寻找消除这些问题的可能方法,但我认为我缺少一些基本的东西;我只是不能让它做我想做的事。

目前让我感到难过的一个案例是:我有一个std::vector名为data;的集合。我所追求的条件是当该size()集合达到某个阈值时。那么,本质上,我希望我的condition仿函数在何时返回真data.size() >= threshold,否则返回假。但我一直无法用 lambda 语法表达它。

到目前为止,我能想到的最好的(至少可以编译,尽管它不起作用)是这样的:

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

问题是,lambda 函数存储了data向量的副本,而不是引用。所以size()在副本上调用,而不是你正在修改的原始对象。这可以通过包装datawith来解决boost::ref,它存储一个引用:

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

您还可以使用普通>=运算符而不是std::greater_equal<>在 lambda 函数的定义中,并将它们组合在一起:

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