Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'

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?

like image 784
Apaar Madan Avatar asked Dec 01 '17 17:12

Apaar Madan


People also ask

Can lvalue bind to rvalue reference?

An lvalue reference can bind to an lvalue, but not to an rvalue.

What are Lvalues and Rvalues in C++?

Lvalues and rvalues are fundamental to C++ expressions. Put simply, an lvalue is an object reference and an rvalue is a value. The difference between lvalues and rvalues plays a role in the writing and understanding of expressions.

What is R value reference in C++?

“r-value” refers to the data value that is stored at some address in memory. References in C++ are nothing but the alternative to the already existing variable. They are declared using the '&' before the name of the variable.

Is const a lvalue?

Such a reference is called an lvalue reference to a const value (sometimes called a reference to const or a const reference). In the above program, we bind const reference ref to modifiable lvalue x . We can then use ref to access x , but because ref is const, we can not modify the value of x through ref .


1 Answers

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)
like image 100
cpplearner Avatar answered Oct 20 '22 09:10

cpplearner