When applying const to a T that is deduced as an Lvalue reference (for example, when passing an Lvalue to a function that takes universal reference), the modifier is ignored. Suppose we pass a regular Lvalue int, const T which should be converted to const int& is being converted to just int&.
Here is an example:
#include <iostream>
template<typename T>
const T foo(T&& a)
{
// const T b{ 1 }; This would result in compile-error, cause b is just int&
const T b{ a };
return b;
}
int main()
{
int x = 5;
foo(x);
}
Here is what I got in C++ insights:
#include <iostream>
template<typename T>
const T foo(T && a)
{
const T b = {a} /* NRVO variable */;
return b;
}
/* First instantiated from: insights.cpp:13 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int & foo<int &>(int & a)
{
int & b = {a}; // As you see I'm getting an int& here and in return type also
return b;
}
#endif
int main()
{
int x = 5;
foo(x);
return 0;
}
You can solve this issue by applying std::remove_reference to the T, and then adding the const and reference, like so:
#include <iostream>
#include <type_traits>
template<typename T>
const std::remove_reference_t<T>& foo(T&& a)
{
const std::remove_reference_t<T>& b{ a };
const std::remove_reference_t<T>& c{ 5 }; // Can use Rvalues now
return b;
}
int main()
{
int x = 5;
foo(x);
}
I was just wondering if this behavior has some explanation? Where else can this behavior rise up? If I'm missing something, I'd appreciate your comments.
It helps to think in east const terms. Qualifiers like const associate to the left except when there is nothing to the left - but const T and T const actually mean the same thing. const applies to the whole T looking at it from the right (east) side.
When T is int& then const T becomes int& const, which is rather pointless since a reference is immutable anyway.
Had it been pointers, it would become clearer. If T is int* then const T and T const becomes int* const which is an immutable pointer, but the object it is pointing at is not const and can be changed:
using T = int*;
int x = 10;
const T b = &x;
*b = 20; // x is now 20
// b = &x; // error, the pointer is const so you can't assign to it
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With