Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why binding rvalue to a const type makes it an lvalue?

This question may not have the best title but here is the code that will explain what I am trying to ask.

This code runs and prints "lvalue" but If I remove const from MyPair’s first type, it gives me the expected output, which is "rvalue". I would like to know what role const plays here?

#include <iostream>
#include <utility>
#include <string>


using MyPair = std::pair<const std::string, int>;


void func(std::string&& str)
{
    std::cout << "rvalue" << std::endl;
}

void func(const std::string& str)
{
    std::cout << "lvalue" << std::endl;
}

template<typename T>
void func_forward(T&& p)
{
    func(std::forward<T>(p).first);
}

void test(MyPair&& p)
{
    func_forward(std::move(p));
}

int main()
{
    test({"hello", 3});
    return 0;
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

In C++, an rvalue is a temporary object that does not have a stable location in memory. We can take the address of an lvalue, but not of an rvalue. An rvalue can be bound to an rvalue reference (T&&) to prolong its lifetime, and to lvalue references to const (const T&), but not to plain lvalue references (T&).

When the first element of the pair is declared as const, you can’t bind a non-const rvalue reference (std::string&&) to it. The reason is that it could allow modifying a const object, which is not allowed in C++. So, the overload for lvalues is selected, i.e., void func(const std::string& str).

The important point here is that std::string&& and const std::string& are not the same thing. The first one is a reference to a temporary string (which could be modified), and the second one is a const lvalue reference that could refer to either an lvalue or an rvalue but will not allow modification of the object it refers to.

When you remove the const from MyPair, the first argument becomes modifiable, and hence, it is allowed to bind it to the non-const rvalue reference (std::string&&). So, in that case, the rvalue version of the func function is called.

To sum it up, the role of const here is to restrict the modification of the object. If an object is const, you can’t bind a non-const rvalue reference to it, as it would allow the modification of a const object.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading