template<typename T>
void f(T a, const T& b)
{
++a; // ok
++b; // also ok!
}
template<typename T>
void g(T n)
{
f<T>(n, n);
}
int main()
{
int n{};
g<int&>(n);
}
Please note: b
is of const T&
and ++b
is ok!
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.
I know that there is already an accepted answer which is correct but just to add to it a little bit, even outside the realm of templates and just in function declarations in general...
( const T& )
is not the same as
( const T )
In your example which matches the first, you have a const reference. If you truly want a const value that is not modifiable remove the reference as in the second example.
来源:https://stackoverflow.com/questions/54480599/why-is-const-t-not-sure-to-be-const