1

注意:以下内容同样适用于 Boost.Thread 和 C++11 线程。

我有一个条件变量,它实际上是一个简单的布尔变量。

// assume these are global
mutex m;
condition_variable c;
boolean b = false;

我想使用wait(lock, predicate)语法。例如,我可以使用 lambda:

c.wait(lock, [] () { return b; });

但我认为应该有一种更惯用的方式将变量包装为可调用对象。所以我发现reference_wrapper提供了一个operator()检索包装值的方法。因此我尝试了:

c.wait(lock, cref(b));

但是g++ (4.9.1) 不编译它,争论no matching function for call to '(boost::reference_wrapper<const bool>) ()'(如果我使用std::ref错误有些不同,但仍然不编译)。

不应该有reference_wrapper资格作为条件变量的适当谓词吗?如果不是,为什么?在这种情况下,什么是正确的包装器b

编辑:所以@Praetorian 已经非常正确地解释了我的错误,但是,在 Boost 或标准上真的没有这样的东西(这里可能有错误):

template<typename T>
struct as_callable {
    T &objref;
    as_callable(T &r) : objref(r) {}
    T &operator()() {
        return objref;
    }
};
4

2 回答 2

1

除了恰当地解释出了什么问题的其他答案之外,我想我也许可以解释您是如何得出错误的期望的。

瞧,还有 Boost Phoenix 的版本,令人惊讶的是ref()cref()它以 Phoenix Lazy Actor 的形式提供了参考。即:phx::ref()and phx::cref()are functors

这意味着您可以简单地使用

c.wait(lock, phx::cref(b));

你可能在过去的某个地方遇到过它。

于 2014-09-15T20:34:43.957 回答
1

std::reference_wrapper::operator()仅在reference_wrapper存储可调用对象时可用,而普通bool对象不可用。使用 lamdba 作为谓词。

如果该布尔值在与您的条件变量等待它的线程不同的线程中被修改,还可以考虑使用std::atomic_bool而不是普通的。bool


如果您真的想使用包装器而不是 lambda,您可以编写一个简单的包装器类,该类operator()在调用时重载并返回存储的布尔值。

struct bool_wrapper
{
    bool_wrapper(bool& b) : b_(&b) {}
    bool *b_;

    bool operator()() const noexcept { return *b_; }
};

现在您可以使用此类包装布尔值并将其传递给condition_variable::waitas

c.wait(lock, bool_wrapper(b));

现场演示

于 2014-09-15T18:36:54.273 回答