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);
}
Обратите внимание: b
имеет значение const T&
, а ++b
в порядке!
Почему const T&
не обязательно является константой?
Добро пожаловать в константу и ссылка, выходящая из строя . Когда Вы имеете const T&
, к ссылке относятся T
и const
- также. Вы звоните g
как [1 126]
g<int&>(n);
, таким образом, Вы указали, что , Вы на самом деле звоните , и Вы на самом деле не изменяете константу. Имел Вас, звонил затем , Так как T
int&
. Когда мы применяем ссылку на lvalue ссылку, эти два ссылочных коллапса к единственному, таким образом int& &
становится всего int&
. Затем мы добираемся до правила от [1 125] [dcl.ref]/1, который указывает, что, если Вы подаете заявку const
к ссылке, она отбрасывается, таким образом int& const
просто становится int&
(обратите внимание, что Вы не можете на самом деле объявить int& const
, она должна прибыть из определения типа или шаблона). Это означает для [1 127] g<int&>(n);
void f(int& a, int& b)
g
, как g<int>(n);
// or just
g(n);
T
будет int
, и f
искоренялся бы как [1 131] void f(int a, const int& b)
T
больше не ссылка, const
и эти &
относятся это, и Вы получили бы ошибку компилятора для попытки изменить постоянную переменную.
Я знаю, что уже существует принятый ответ, который корректен, но только добавить к нему немного, даже вне области шаблонов и только в объявлениях функции в целом...
( const T& )
не то же как
( const T )
В Вашем примере, который соответствует первому, у Вас есть ссылка константы. Если Вы действительно хотите значение константы, которое не является модифицируемым, удаляют ссылку как во втором примере.