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;
}
>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.