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

air*_*man 13 c++ perfect-forwarding c++11 std-function

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

R operator()(ArgTypes...) const;
Run Code Online (Sandbox Code Playgroud)

并不是

R operator()(ArgTypes&&...) const;
Run Code Online (Sandbox Code Playgroud)

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

我部分重新实现了std :: function来测试这个,我发现如果我使用&&,当我稍后尝试通过值将参数传递给operator()时,我从g ++中得到"无法将'xxx'左值'绑定到'xxx &&'" .我认为我对rvalue/forwarding概念有了足够的把握,但我还是不能理解这一点.我错过了什么?

Xeo*_*Xeo 14

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

完美转发背后的整个技巧是模板参数推导部分,它与参考折叠一起,是完美的转发.

我只是方便地链接到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
}
Run Code Online (Sandbox Code Playgroud)