The following code fails to compile:
#include <iostream>
using namespace std;
int add2(const int& x)
{
return x + 2;
}
template <typename T>
T add2T(T&& x) {
return add2(std::forward<T>(x));
}
int main(int argc, char** argv) {
int x = 0;
cout << "Add 2" << endl;
cout << add2(2) << endl;
cout << add2(x) << endl;
cout << "Add 2T" << endl;
cout << add2T(10) << endl;
cout << add2T(x) << endl;
return 0;
}
With this message:
main.cpp: In instantiation of 'T add2T(T&&) [with T = int&]':
main.cpp:26:20: required from here
main.cpp:12:16: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
return add2(std::forward<T>(x));
~~~~^~~~~~~~~~~~~~~~~~~~
I'm not sure why the compiler is trying to bind the non-const lvalue reference to an rvalue. The forward should decay into an lvalue reference anyways, right?
The problem is not related to forward.
In the call add2T(x)
, the deduced template argument T
is int&
. (Only in this way can T&&
be an lvalue reference type.) Thus the return type is also int&
. However, the operand of return
(namely add2(std::forward<T>(x))
) is an rvalue that cannot be used to initialize int&
. Hence the error message.
If you want to prevent the return type from becoming a reference type, you can apply std::decay_t
:
template <typename T>
std::decay_t<T> add2T(T&& x)