Добро пожаловать в const и ссылка сворачивается .Когда у вас есть const T&
, ссылка применяется к T
, как и const
.Вы звоните g
как
g<int&>(n);
, поэтому вы указали, что T
- это int&
.Когда мы применяем ссылку на ссылку lvalue, две ссылки сворачиваются в одну, поэтому int& &
становится просто int&
.Затем мы получим правило из [dcl.ref] / 1 , которое гласит, что если вы примените const
к ссылке, она будет отброшена, поэтому int& const
просто станет int&
(обратите внимание, что вына самом деле не может объявить int& const
, это должно быть из typedef или шаблона).Это означает, что для
g<int&>(n);
вы на самом деле звоните
void f(int& a, int& b)
и фактически не изменяете константу.
Если бы вы назвали g
как
g<int>(n);
// or just
g(n);
тогда T
будет int
, а f
будет помечено как
void f(int a, const int& b)
, поскольку T
больше не является ссылкой,const
и &
будут применены к нему, и вы получите ошибку компилятора при попытке изменить постоянную переменную.