I'm struggling to understand why std::forward
has an overload taking an rvalue reference, as documented here. According to this the overload taking an lvalue reference is sufficient to handle all the cases, given the reference collapsing rules. This makes sense to me (at least at my current level of understanding of the reference collapsing), so I decided to put together a small reproducer mimicking the usual factory pattern to investigate the calls to forward:
#include <iostream>
template<typename T> T&& forw(typename std::remove_reference<T>::type &t){
std::cout<<"forw&" << std::endl;
return static_cast<T&&>(t);
}
template<typename T> T&& forw(typename std::remove_reference<T>::type &&t){
std::cout<<"forw&&" << std::endl;
static_assert(!std::is_lvalue_reference<T>::value, "invalid rvalue to lvalue conversion");
return static_cast<T&&>(t);
}
template<typename T> void constructor(T &t){
std::cout << "constructor(T &t)" << std::endl;
}
template<typename T> void constructor(T &&t){
std::cout << "constructor(T &&t)" << std::endl;
}
template<typename T> void factory(T &&t){
constructor(forw<T>(t));
}
int main(){
std::string s;
std::cout << "** Calling factory(s)" << std::endl;
factory(s);
std::cout << "\n** Calling factory(std::string())" << std::endl;
factory(std::string());
return 0;
}
Compiling with g++ 10.2.0 and running I get:
$ ./a.out
** Calling factory(s)
forw&
constructor(T &t)
** Calling factory(std::string())
forw&
constructor(T &&t)
So it seems that the overload of forw
taking an lvalue reference is always called, and that the argument is always perfectly forwarded to the constructor. So what's the purpose of the second overload?