According to https://en.cppreference.com/w/cpp/language/reference, forwarding references are either,
- function parameter of a function template declared as rvalue reference.
- auto&&.
Here at https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers Scott Meyers explained that, although vector::push_back(T&& x) takes a T&&, it is not a universal reference. It's just a plain rvalue reference.
However, my below code compiles and runs well:
#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 &&)
}
It sounds like T&& is treated as a forwarding reference here, because f(T&& x) accepts both lvalue and rvalue references. But f(T&& x) is a class template member; it is not a standalone function template. Is this against the forwarding reference definition that I mentioned above?
<<\ADD-->
In the case of the forwarding reference in a function template, the function template itself also needs to instantiate based on a specific type T. We can express this explicitly:
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&> and f<\int&&> are two different instances of the above function template. They are not pointing to the same function address behind the scenes either, similar to class template instantiation. Of course, we need class object to use its functions.
<--End ADD>