我看到了类似的用法
#include <iostream>
#include <functional>
using namespace std;
template<typename FN>
void Foo(FN&& Fn)
{
Fn();
}
void b()
{
cout << "2." << endl;
}
int main()
{
Foo([](){ cout << "1." << endl; });
Foo(&b);
auto c = []() { cout << "3." << endl; };
Foo(c);
std::function<void(void)> d = c;
Foo(d);
return 0;
}
我很确定’c’是一个左值,但我可以相信有一些lambda型演绎shenanigans.但我几乎100%肯定,d是左值.
如果函数接受rvalue,为什么模板化的东西有效,但d是左值?
此外,为什么会像那样写Foo的签名而不仅仅是
template<typename FN>
void Foo(FN Fn)
最佳答案 T&& amp;& amp; amp;& amp;很棘手
它们的设计目的是为了推导T&& amp; “转发参考”(或“通用参考”).
首先,参考崩溃.假设您有一个未知类型X.现在不推导出X.
然后,如果我们检查以下类型的变量:
typedef X x0;
typedef X& x1;
typedef X const& x2;
typedef X&& x3;
我们将X设置为int,int&,int const&和int&&,我们得到:
X is ---> int int& int const& int&&
X int int& int const& int&&
X& int& int& int const& int&
X const& int const& int& int const& int&
X&& int&& int& int const& int&&
下一部分附带扣除规则.如果你通过X&对T&&在推导的上下文中,T被推断为X&.这导致T&&成为X&通过上述参考折叠规则.类似的事情发生在X const& ;.
如果你通过X&&对于T&&,它推断T为X. T&&成为X&&同样.
在它们中的两个之间,在推导的上下文中,模板 void foo(T& t)是一个通用引用(现在称为转发引用).
您可以使用std :: forward< T>(t)恢复t的r / l值类别,因此名称转发引用.
这允许一个模板处理l和r值,并且如果需要,可以使用std :: forward和类似的机制稍微不同地表现.
只处理rvalues需要额外的工作:你必须使用SFINAE或其他重载(可能使用= delete).只处理左值很容易(只需用T&推断).