En c ++ 14 decltype(auto)
se introduce el idioma.
Por lo general, su uso es permitir que las auto
declaraciones usen las decltype
reglas en la expresión dada .
Buscando ejemplos de uso "bueno" del idioma solo puedo pensar en cosas como las siguientes (por Scott Meyers ), a saber, para la deducción de tipo de retorno 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 otros ejemplos en los que esta nueva función de lenguaje sea útil?
decltype(auto)
algo similartemplate<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }
, aunque luego me di cuenta de que tenía que usarlo, loreturn (p.first);
que sorprendentemente funciona (pero IIRC, incluso está destinado).decltype(auto)
puede hacer que algo se copie / mueva al objeto declarado, en contra de lo esperado.Respuestas:
Reenvío de tipo de reenvío en código genérico
Para el código no genérico, como el ejemplo inicial que proporcionó, puede seleccionar manualmente para obtener una referencia como tipo de retorno:
pero en el código genérico desea poder reenviar perfectamente un tipo de retorno sin saber si se trata de una referencia o un valor.
decltype(auto)
te da esa habilidad:Retraso en la deducción del tipo de devolución en plantillas recursivas
En estas preguntas y respuestas de hace unos días, se encontró una recursión infinita durante la creación de instancias de plantilla cuando se especificó el tipo de retorno de la plantilla en
decltype(iter(Int<i-1>{}))
lugar dedecltype(auto)
.decltype(auto)
se utiliza aquí para retrasar la deducción del tipo de devolución después de que se haya establecido el polvo de la creación de instancias de plantilla.Otros usos
También puede usarlo
decltype(auto)
en otros contextos, por ejemplo, el borrador del Estándar N3936 también establece7.1.6.4 autoespecificador [dcl.spec.auto]
El borrador también contiene este ejemplo de inicialización variable:
fuente
(i)
vsi
algo nuevo en C ++ 14?decltype(expr)
y yadecltype((expr))
son diferentes en C ++ 11, esto generaliza ese comportamiento.auto
habría hecho el trabajo igual de bien, ya que el resultado es devuelto por el valor de todos modos ... ¿O me perdí? ¿alguna cosa?Citando cosas de aquí :
decltype(auto)
es principalmente útil para deducir el tipo de retorno de las funciones de reenvío y envoltorios similares , donde desea que el tipo "rastree" exactamente alguna expresión que está invocando.Por ejemplo, dadas las siguientes funciones:
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 , hacerlo 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 se escribe la declaración de devolución.
Por ejemplo, las dos funciones siguientes tienen diferentes tipos de retorno:
string
, el segundo vuelvestring&
, que es una referencia a la variable localstr
.De la propuesta puede ver más usos previstos.
fuente
auto
para devolución?auto
devolución), pero el OP solicitó específicamente usos dedecltype(auto)
.auto lookup_a_string() { ... }
? ¿Es siempre un tipo sin referencia? ¿Y porauto lookup_a_string() ->decltype(auto) { ... }
lo tanto se necesita forzar para permitir que se devuelvan referencias (en algunos casos)?auto
se define en términos de plantilla de pasar por valor, por lo que sí, no puede ser una referencia. Por favor, espereauto
puede ser cualquier cosa, incluida una referencia, por supuesto.std::vector
. Di que tienestemplate<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }
. LuegoS<bool>::operator[]
devolverá unas referencias colgantes debido a la especialización destd::vector<bool>
. Cambiar el tipo de retorno paradecltype(auto)
evitar este problema.