C++11 std::function 和完美转发

标签 c++ c++11 perfect-forwarding std-function

为什么 C++ 标准中 std::function<>::operator() 的定义是:

R operator()(ArgTypes...) const;

而不是

R operator()(ArgTypes&&...) const;

?

有人会认为要正确转发参数,我们需要 && 然后使用 std::forward<ArgTypes>...转接调用时在函数体中?

我部分重新实现了 std::function 来测试它,我发现如果我使用 &&,当我稍后尝试按值传递参数时,我会从 g++ 中得到“无法将 'xxx' 左值绑定(bind)到 'xxx&&'”运算符(operator)()。我认为我对右值/转发概念有足够的了解,但我仍然无法理解这一点。我错过了什么?

最佳答案

仅当函数本身(在本例中为 operator())被模板化并且模板参数被推导出时,完美转发才有效。对于 std::function,您从 class 本身的模板参数中获取 operator() 参数类型,这意味着它们永远不会从任何论点推导出来。

完美转发背后的全部技巧是模板参数推导部分,与引用折叠一起,就是完美转发。

我只是方便地链接到 my other answer about std::forward在这里,我解释了完美转发(和 std::forward)的工作原理。

请注意,std::functionoperator() 不需要完美转发,因为用户自己决定参数应该是什么。这也是你不能只将 && 添加到 operator() 的原因;举个例子:

void foo(int){}

int main(){
  // assume 'std::function' uses 'ArgTypes&&...' in 'operator()'
  std::function<void(int)> f(foo);
  // 'f's 'operator()' will be instantiated as
  // 'void operator()(int&&)'
  // which will only accept rvalues
  int i = 5;
  f(i); // error
  f(5); // OK, '5' is an rvalue
}

关于C++11 std::function 和完美转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11135354/

相关文章:

c++ - 模板化成员函数和参数转发

c++ - 不转发通用引用会出现什么样的问题?

c++ - 如何在 Visual Studio 中使用 GoogleMock?

c++ - 为什么 C++ 中的内置堆栈接口(interface)没有 clear() 函数?

c++ - 无法绑定(bind)可变函数并保存到 std::function

c++ - 无法将 std::chrono 与 std::future 一起使用 - 未找到 GLIBCXX_3.4.19

c++ - 需要引用标准关于 main 函数作为模板函数的合法性

c++ - std::move 的简写

c++ - 取消初始化对象是什么意思?

c++ - 未定义的 namespace 引用 - gsoap 错误