operador de flecha (->) en el encabezado de la función

128

Encontré el siguiente código:

template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) {
   return a+b;
}

Hay una cosa que no puedo entender:

¿Dónde podría averiguar qué significa el operador de flecha ( ->) en el encabezado de la función? Supongo, lógicamente, que el ->operador determina un tipo, que autose deducirá, pero quiero aclararlo. No puedo encontrar ninguna información.

usuario1234567
fuente
2
Es parte de la sintaxis de tipo de retorno final. Ver stackoverflow.com/a/4113390/962089
chris
2
No es un operador sino una parte de la sintaxis.
texasbruce
1
En respuesta a "¿dónde puedo leer?", La especificación C ++ es más autorizada. A falta de fondos o deseo de gastar $$, el último borrador de trabajo a menudo es lo suficientemente cercano y sin costo. Estas especificaciones son altamente habladas en el techo, por lo que carecen de familiaridad con la lectura de especificaciones ISO, intente cplusplus.com o cppreference.com u otros sitios similares que no sean autoritativos, pero generalmente son muy precisos. Nota: el tipo de retorno final puede omitirse comenzando con C ++ 14.
Les

Respuestas:

205

En C ++ 11, hay dos sintaxis para la declaración de función:

    declaraciones de argumento de identificador de tipo de retorno ( ... )

y

    auto identificador ( argumento-declaraciones ... ) -> return_type

Son equivalentes Ahora, cuando son equivalentes, ¿por qué quieres usar este último? Bueno, C ++ 11 introdujo esta decltypecosa genial que te permite describir el tipo de expresión. Por lo tanto, es posible que desee derivar el tipo de retorno de los tipos de argumento. Entonces intentas:

template <typename T1, typename T2>
decltype(a + b) compose(T1 a, T2 b);

y el compilador le dirá que no sabe qué ay bestá en el decltypeargumento. Esto se debe a que solo los declara la lista de argumentos.

Puede solucionar el problema fácilmente utilizando declvallos parámetros de plantilla que ya están declarados. Me gusta:

template <typename T1, typename T2>
decltype(std::declval<T1>() + std::declval<T2>())
compose(T1 a, T2 b);

excepto que ahora se está volviendo muy detallado. Entonces se propuso e implementó la sintaxis de declaración alternativa y ahora puede escribir

template <typename T1, typename T2>
auto compose(T1 a, T2 b) -> decltype(a + b);

y es menos detallado y las reglas de alcance no tuvieron que cambiar.


Actualización de C ++ 14: C ++ 14 también permite solo

    auto identificador ( argumento-declaraciones ... )

siempre que la función esté completamente definida antes de su uso y todas las returndeclaraciones se deduzcan al mismo tipo. La ->sintaxis sigue siendo útil para las funciones públicas (declaradas en el encabezado) si desea ocultar el cuerpo en el archivo fuente. Obviamente, eso no se puede hacer con las plantillas, pero hay algunos tipos concretos (generalmente derivados de la metaprogramación de plantillas) que son difíciles de escribir de otra manera.

Jan Hudec
fuente
2
Muy buena, ordenada e informativa respuesta @ Jan Hudec. Pulgares arriba. ¿Hay algo cambiado C++14cuando uso autopara returnescribir en dicha función sin la necesidad de la -> decltype(a + b)parte? ¿Es redundante en este momento o tiene otros casos en los que todavía debería usarse? o es una extensión específica del compilador?
Shadi
1
@Shadi, C ++ 14 incluye N3638 , que permite la deducción del tipo de retorno declarado como auto, sin la ->notación, siempre que la función esté completamente definida antes de su uso y todas las returndeclaraciones se deduzcan al mismo tipo. La ->notación sigue siendo útil si desea utilizar la deducción para la función pública mientras oculta el cuerpo en el archivo fuente.
Jan Hudec
23

En inglés simple dice que el tipo de retorno es el tipo inferido de la suma de ay b.

Murrekatt
fuente