Why is `const T&` not sure to be const?
Welcome to const and reference collapsing. When you have const T&
, the reference gets applied to T
, and so does the const
. You call g
like
g<int&>(n);
so you have specified that T
is a int&
. When we apply a reference to an lvalue reference, the two references collapse to a single one, so int& &
becomes just int&
. Then we get to the rule from [dcl.ref]/1, which states that if you apply const
to a reference it is discarded, so int& const
just becomes int&
(note that you can't actually declare int& const
, it has to come from a typedef or template). That means for
g<int&>(n);
you are actually calling
void f(int& a, int& b)
and you are not actually modifying a constant.
Had you called g
as
g<int>(n);
// or just
g(n);
then T
would be int
, and f
would have been stamped out as
void f(int a, const int& b)
Since T
isn't a reference anymore, the const
and the &
get applied to it, and you would have received a compiler error for trying to modify a constant variable.