In the context of a template, the following "reference collapsing" rules are applied:
template <typename T>
void foo(T && t)
{
//T& & -> T&
//T& && -> T&
//T&& & -> T&
//T&& && -> T&&
}
Why does the language prohibit "universal references" from having const
qualifiers?
template <typename T>
void foo(T const && t)
It would seem to make sense if the type had resolved to a reference (3 out of the 4 cases).
I'm sure this idea is incompatible with some other design aspect of the language, but I can't quite see the full picture.
T * const would mean you can modify the T value pointed to by foo , but you cannot modify the pointer itself; so you can't say foo++; (*foo)++ because the first statement would increment (modify) the pointer.
It is simple in concept: variables declared with 'const' added become constants and cannot be altered by the program. However it is also used to bodge in a substitute for one of the missing features of C++ and there it gets horridly complicated and sometimes frustratingly restrictive.
int const* is pointer to constant integer This means that the variable being declared is a pointer, pointing to a constant integer. Effectively, this implies that the pointer is pointing to a value that shouldn't be changed.
The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it.
Originally the rvalue reference proposal said that the transformation happens if P
is "an rvalue reference type". However, a defect report later noticed
Additionally, consider this case:
template <class T> void f(const T&&); ... int i; f(i);
If we deduce
T
asint&
in this case thenf(i)
callsf<int&>(int&)
, which seems counterintuitive. We prefer thatf<int>(const int&&)
be called. Therefore, we would like the wording clarified that theA&
deduction rule in 14.8.2.1 [temp.deduct.call] paragraph 3 applies only to the formT&&
and not tocv T&&
as the note currently implies.
There appears to have been a time period where const T &&
, with T
being U&
, was transformed to const U&
. That was changed to be consistent with another rule that says that const T
, where T
is U&
would stay U&
(cv-qualifiers on references are ignored). So, when you would deduce T
in above example to int&
, the function parameter would stay int&
, not const int&
.
In the defect report, the reporter states "We prefer that f<int>(const int&&)
be called", however provides no reason in the defect report. I can imagine that the reason was that it seemed too intricate to fix this without introducing inconsistency with other rules, however.
We should also keep in mind that the defect report was made at a time where rvalue references could still bind to lvalues - i.e const int&&
could bind to an int lvalue. This was prohibited only later on, when a paper by Dave & Doug, "A Safety Problem with RValue References", appeared. So, it seems to me that a deduction that works (at that time) was worth more than a deduction that simply was counter intuitive and dropped qualifiers.
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