将局部变量绑定到闭包的最便宜方式

时间:2012-04-07 11:19:49

标签: c++ c++11

我相信以下是将局部变量绑定到闭包的最便宜方式:

void ByRValueReference(A&& a) {
}

std::function<void ()> CreateClosureByRValueReference() {
  A a;
  std::function<void ()> f = std::bind(&ByRValueReference, std::move(a)); // !!!
  return f;
}

但是,它不能在Clang 3.1下编译:

error: no viable conversion from '__bind<void (*)(A &&), A>' to 'std::function<void ()>'

和gcc 4.6.1:

/usr/include/c++/4.6/functional:1778:2: error: no match for call to ‘(std::_Bind<void (*(A))(A&&)>) ()’

我违反了标准,还是只是破坏了标准库?

1 个答案:

答案 0 :(得分:3)

这是std::bind的设计。完整规范在20.8.9.1.2函数模板bind [func.bind.bind]中,但在这种情况下,第10段的最后一个子弹(描述如何使用绑定参数)适用:

  

- 否则,该值为tid,其类型ViTiD cv &

换句话说,std::move(a)将导致调用包装器存储A(来自移动构造),然后当使用operator()时,此成员将被转发作为左值(附加的cv限定符与调用包装器的cv限定符匹配,但我离题了)。即使它是作为右值传递的。

这种不匹配可以通过lambda解决:

std::bind([](A& a) { ByRValueReference(std::move(a)); }, std::move(a))

可以认为,更明确的是,对结果调用包含的进一步调用是可疑的(因为A成员可能已被移除),但我并不过分喜欢这种行为。 std::bind作为一个整体。