A partir de C ++ 14, a menudo lo son.
C ++ 14 agrega un caso marginal donde los paréntesis alrededor de un valor de retorno pueden alterar la semántica. Este fragmento de código muestra la declaración de dos funciones. La única diferencia son los paréntesis alrededor del valor de retorno.
int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))
En el primero func1
devuelve un int
y en el segundo func1
devuelve un int&
. La diferencia semántica está directamente relacionada con los paréntesis que la rodean .
El auto
especificador en su forma más reciente se introdujo en C ++ 11. En la especificación del lenguaje C ++ se describe como:
Especifica que el tipo de variable que se declara se deducirá automáticamente de su inicializador. Para funciones, especifica que el tipo de retorno es un tipo de retorno final o se deducirá de sus declaraciones de retorno (desde C ++ 14)
Además, C ++ 11 introdujo el decltype
especificador que se describe en las especificaciones del lenguaje C ++ :
Inspecciona el tipo declarado de una entidad o consulta el tipo de retorno de una expresión.
[recorte]
Si el argumento es el nombre sin paréntesis de un objeto / función, o es una expresión de acceso de miembro (object.member o pointer-> member), entonces decltype especifica el tipo declarado de la entidad especificada por esta expresión.
Si el argumento es cualquier otra expresión de tipo T, entonces
a) si la categoría de valor de la expresión es xvalue, entonces decltype especifica T &&
b) si la categoría de valor de expresión es lvalue, entonces decltype especifica T &
c) de lo contrario, decltype especifica T
[recorte]
Tenga en cuenta que si el nombre de un objeto está entre paréntesis, se convierte en una expresión lvalue, por lo que decltype (arg) y decltype ((arg)) suelen ser tipos diferentes.
En C ++ 14, decltype(auto)
se permitía la capacidad de uso para los tipos de devolución de funciones. Los ejemplos originales son donde entra en juego la diferencia semántica entre paréntesis. Revisando los ejemplos originales:
int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))
decltype(auto)
permite que el tipo de retorno final en la función se deduzca de la entidad / expresión en la declaración de retorno. En la primera versión return var1;
es efectivamente lo mismo que devolver el tipo decltype(var1)
(un int
tipo de devolución según la regla 1 anterior) y en el segundo caso return (var1);
es efectivamente lo mismo que decltype((var1))
(un int &
tipo de devolución según la regla 2b).
Los paréntesis hacen el tipo de retorno en int&
lugar de int
, por lo tanto, un cambio en la semántica. Moraleja de la historia: "No todos los paréntesis de un tipo de devolución son iguales"