ejemplo c++ auto c++14 decltype return-type-deduction

c++ - ejemplo - ¿Cuáles son algunos usos de decltype(auto)?



auto c++ ejemplo (2)

En c ++ 14 se decltype(auto) el decltype(auto) idioma.

Por lo general, su uso es permitir que auto autodeclaraciones usen las reglas de decltype en la expresión dada .

Buscando ejemplos de "buen" uso de la expresión idiomática, solo puedo pensar en cosas como las siguientes (por Scott Meyers ), a saber, para la deducción de un tipo de devolución de una función :

template<typename ContainerType, typename IndexType> // C++14 decltype(auto) grab(ContainerType&& container, IndexType&& index) { authenticateUser(); return std::forward<ContainerType>(container)[std::forward<IndexType>(index)]; }

¿Hay algún otro ejemplo en el que esta nueva función de idioma sea útil?


Devolver tipo de reenvío en código genérico

Para código no genérico, como el ejemplo inicial que proporcionó, puede seleccionar manualmente para obtener una referencia como tipo de devolución:

auto const& Example(int const& i) { return i; }

pero en el código genérico desea poder reenviar perfectamente un tipo de devolución sin saber si se trata de una referencia o un valor. decltype(auto) te da esa habilidad:

template<class Fun, class... Args> decltype(auto) Example(Fun fun, Args&&... args) { return fun(std::forward<Args>(args)...); }

Retraso en la deducción del tipo de retorno en plantillas recursivas

En esta sesión de preguntas y respuestas hace unos días, se encontró una recursión infinita durante la instanciación de la plantilla cuando el tipo de devolución de la plantilla se especificaba como decltype(iter(Int<i-1>{})) lugar de decltype(auto) .

template<int i> struct Int {}; constexpr auto iter(Int<0>) -> Int<0>; template<int i> constexpr auto iter(Int<i>) -> decltype(auto) { return iter(Int<i-1>{}); } int main() { decltype(iter(Int<10>{})) a; }

decltype(auto) se utiliza aquí para retrasar la deducción del tipo de devolución una vez que se ha establecido el polvo de la instanciación de la plantilla.

Otros usos

También puede usar decltype(auto) en otros contextos, por ejemplo, el borrador del estándar N3936 también indica

7.1.6.4 autoespecificador [dcl.spec.auto]

1 Los especificadores de tipo auto y decltype(auto) designan un tipo de marcador de posición que se reemplazará más tarde, ya sea por deducción desde un inicializador o por especificación explícita con un tipo de retorno final. El auto -especificador de tipo también se usa para indicar que una lambda es una lambda genérica.

2 El tipo de marcador de posición puede aparecer con un declarador de función en decl-specifier-seq, type-specifier-seq, conversion-function-id o trailing-return-type, en cualquier contexto donde dicho declarador sea válido . Si el declarador de función incluye un tipo de retorno final (8.3.5), eso especifica el tipo de retorno declarado de la función. Si el tipo de devolución declarada de la función contiene un tipo de marcador de posición, el tipo de devolución de la función se deduce de las declaraciones de devolución en el cuerpo de la función, si corresponde.

El borrador también contiene este ejemplo de inicialización de variable:

int i; int&& f(); auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)


Citando cosas desde here :

  • decltype(auto) es principalmente útil para deducir el tipo de devolución de funciones de reenvío y envoltorios similares , donde se desea que el tipo "rastree" exactamente alguna expresión que está invocando.

  • Por ejemplo, dadas las funciones a continuación:

string lookup1(); string& lookup2();

  • En C ++ 11 podríamos escribir las siguientes funciones de contenedor que recuerdan preservar la referencia del tipo de retorno:

string look_up_a_string_1() { return lookup1(); } string& look_up_a_string_2() { return lookup2(); }

  • En C ++ 14, podemos automatizar eso:

decltype(auto) look_up_a_string_1() { return lookup1(); } decltype(auto) look_up_a_string_2() { return lookup2(); }

  • Sin embargo, decltype(auto) no pretende ser una característica ampliamente utilizada más allá de eso.

  • En particular, aunque puede usarse para declarar variables locales , hacer eso probablemente sea solo un antipatrón ya que la referencia de una variable local no debería depender de la expresión de inicialización.

  • Además, es sensible a cómo escribe la declaración de devolución.

  • Por ejemplo, las dos funciones a continuación tienen diferentes tipos de devolución:

decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; } decltype(auto) look_up_a_string_2() { auto str = lookup2(); return(str); }

  • La primera string devuelve, la segunda devuelve la string& , que es una referencia a la variable local str .

A partir de la proposal , puede ver más usos previstos.