c++ - ¿Por qué `const T &` no está seguro de ser const?
templates function-templates (2)
Bienvenidos a const y al
colapso de referencia
.
Cuando tienes
const T&
, la referencia se aplica a
T
, y también lo hace la
const
.
Llamas
g
como
g<int&>(n);
por lo que ha especificado que
T
es un
int&
.
Cuando aplicamos una referencia a una referencia de valor l, las dos referencias se colapsan en una sola, por lo que
int& &
convierte en
int&
.
Luego llegamos a la regla de
[dcl.ref]/1
, que establece que si aplica
const
a una referencia, se descartará, por lo que
int& const
simplemente se convierte en
int&
(tenga en cuenta que en realidad no puede declarar
int& const
, tiene que provienen de un typedef o plantilla).
Eso significa para
g<int&>(n);
en realidad estás llamando
void f(int& a, int& b)
y en realidad no estás modificando una constante.
Habías llamado
g
como
g<int>(n);
// or just
g(n);
entonces
T
sería
int
,
f
habría sido eliminado como
void f(int a, const int& b)
Dado que
T
ya no es una referencia, la
const
y la aplicación
&
se aplican a ella, y usted habría recibido un error de compilación al intentar modificar una variable constante.
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);
}
Tenga en cuenta:
b
es de
const T&
and
++b
está bien!
¿Por qué es
const T&
no estoy seguro de ser const?
Sé que ya hay una respuesta aceptada que es correcta, pero solo para agregarle un poco, incluso fuera del ámbito de las plantillas y solo en las declaraciones de funciones en general ...
( const T& )
no es lo mismo que
( const T )
En su ejemplo que coincide con el primero, tiene una referencia constante. Si realmente desea un valor constante que no sea modificable, elimine la referencia como en el segundo ejemplo.