根据https://en.cppreference.com/w/cpp/language/reference,转发引用是
这里https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers 斯科特·迈耶斯(Scott Meyers)解释说,尽管vector :: push_back(T && x)接受了T &&,但它不是通用参考。这只是一个普通的右值引用。
但是,我下面的代码可以编译并运行良好:
#include <iostream>
template<typename T>
class MyClass
{
public:
void f(T&& x)
{
std::cout << __FUNCSIG__ << std::endl;
}
};
int main()
{
int i = 10;
MyClass<int&> myClass1;
myClass1.f(i); //void __thiscall MyClass<int &>::f(int &)
MyClass<int&&> myClass2;
myClass2.f(10); //void __thiscall MyClass<int &&>::f(int &&)
}
这听起来像T &&在这里被视为转发参考,因为f(T && x)接受左值引用和右值引用。但是f(T && x)是类模板成员;它不是独立的功能模板。这是否违反了我上面提到的转发参考定义?
<< \ ADD->
对于功能模板中的转发引用,功能模板本身也需要基于特定的类型T进行实例化。我们可以明确地表达这一点:
template<class T>
void f(T&& x)
{}
int main() {
int i = 10;
f<int&>(i); // argument is lvalue
f<int&&>(10); // argument is rvalue
}
f <\ int&>和f <\ int &&>是上述功能模板的两个不同实例。它们也没有指向幕后的相同函数地址,类似于类模板实例化。当然,我们需要类对象才能使用其功能。
<-结束添加>
答案 0 :(得分:3)
因为
f(T&& x)
接受左值引用和右值引用
不是。您不是在这里比较相同成员函数。 MyClass<int&>::f
是一个仅接受左值的类的成员函数。同时,MyClass<int&&>::f
是另一个类的成员函数,并且仅接受右值。
类模板不是类。这是一个用来制作类的小甜饼。尽管这些专业化具有相似命名的成员函数,但在不同类中它们仍然是不同的函数。
如果您尝试传递MyClass<int&>::f
一个右值,则您的代码将无法成功构建,
myClass1.f(10); // ERROR
Reference collapsing使生成的f
接受不同值类别的引用,但是实例化该类后,该成员将仅接受特定值类别。它不会像在呼叫参考中那样转发在呼叫站点推断出的值类别。
答案 1 :(得分:0)
关于转发引用的事情是,它们在模板参数推导过程中自动 成为右值引用或左值引用。呼叫者不需要指定他们想要的。
在您的示例中,您已明确指定int&
和int&&
,这将迫使f
具有一种或另一种类型。然后,它会相应地采用左值或右值,但两者都不像转发引用可以:myClass1.f(10);
和myClass2.f(i);
都格式错误。