M. *_* E. 6 c++ templates perfect-forwarding c++11
以下签名声明为std::forward重载:
template<class T> T&& forward(typename remove_reference<T>::type& arg) noexcept;
template<class T> T&& forward(typename remove_reference<T>::type&& arg) noexcept;
Run Code Online (Sandbox Code Playgroud)
现在,考虑以下模板函数:
template<class T> T&& foo_as_always(T&& t)
{
return std::forward<T>(t);
}
Run Code Online (Sandbox Code Playgroud)
如果我写:
int i = 0;
foo_as_always(i);
Run Code Online (Sandbox Code Playgroud)
然后这就是编译器实例化的foo_as_always方式T = int&:
int& foo_as_always(int& t)
{
// Does it call the first signature of std::forward(int&)
return std::forward<int&>(t);
}
Run Code Online (Sandbox Code Playgroud)
如果我写:
foo_as_always(0);
Run Code Online (Sandbox Code Playgroud)
那么编译器实例foo_as_always有T = int:
int&& foo_as_always(int&& t)
{
// Does it call the second signature of std::forward(int&&)?
return std::forward<int>(t);
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,t变量都是任何表达式中的l值.编译器如何知道std::forward必须调用函数的哪个重载?
因为你明确地提供了模板参数(你提供的<T>); 没有类型扣除.
在通话中foo_as_always(i);,i是T推导出的左值int &,这是你提供的std::forward.
在通话中foo_as_always(0);,0是一个rvalue,因此T推断出来int,这也是你提供的std::forward.
在这两种情况下,它最终会调用第一个重载,当然,因为它t是一个左值,正如你所说.但是返回类型不同 - 在第一种情况下,它是int& &&,所以int&,在第二种情况下,它是int &&.