No c ++ 14, o decltype(auto)
idioma é introduzido.
Normalmente, seu uso é permitir que as auto
declarações usem as decltype
regras na expressão especificada .
Procurando exemplos de uso "bom" do idioma, só consigo pensar em coisas como as seguintes (de Scott Meyers ), especificamente para dedução do tipo de retorno de uma função :
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
Existem outros exemplos em que esse novo recurso de idioma é útil?
decltype(auto)
algo parecidotemplate<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }
, mas percebi que tinha que usar oreturn (p.first);
que surpreendentemente funciona (mas o IIRC é o que se destina).decltype(auto)
pode fazer com que algo seja copiado / movido para o objeto declarado, contrariando as expectativas.Respostas:
Encaminhamento de tipo de retorno em código genérico
Para código não genérico, como o exemplo inicial que você deu, você pode selecionar manualmente para obter uma referência como um tipo de retorno:
mas no código genérico você deseja encaminhar perfeitamente um tipo de retorno sem saber se está lidando com uma referência ou um valor.
decltype(auto)
lhe dá essa capacidade:Atraso na dedução do tipo de retorno em modelos recursivos
Nestas perguntas e respostas , há alguns dias, uma recursão infinita durante a instanciação do modelo foi encontrada quando o tipo de retorno do modelo foi especificado como em
decltype(iter(Int<i-1>{}))
vez dedecltype(auto)
.decltype(auto)
é usado aqui para atrasar a dedução do tipo de retorno após a poeira da instanciação do modelo.Outros usos
Você também pode usar
decltype(auto)
em outros contextos, por exemplo, o rascunho da norma N3936 também declara7.1.6.4 especificador automático [dcl.spec.auto]
O rascunho também contém este exemplo de inicialização de variável:
fonte
(i)
vsi
é algo novo no C ++ 14?decltype(expr)
e jádecltype((expr))
são diferentes no C ++ 11, isso generaliza esse comportamento.auto
teria feito o trabalho tão bem quanto o resultado é retornado por valor de qualquer maneira ... Ou eu perdi alguma coisa?Citando coisas daqui :
decltype(auto)
é útil principalmente para deduzir o tipo de retorno de funções de encaminhamento e wrappers similares , onde você deseja que o tipo “rastreie” exatamente alguma expressão que você está chamando.Por exemplo, dadas as funções abaixo:
No entanto,
decltype(auto)
não se destina a ser um recurso amplamente usado além disso.Em particular, embora possa ser usado para declarar variáveis locais , isso provavelmente é apenas um antipadrão, já que a referência de uma variável local não deve depender da expressão de inicialização.
Além disso, é sensível à forma como você escreve a declaração de retorno.
Por exemplo, as duas funções abaixo têm diferentes tipos de retorno:
string
, o segundo retornastring&
, que é uma referência à variável localstr
.A partir da proposta, você pode ver mais usos pretendidos.
fonte
auto
para devolução?auto
retorno), mas o OP solicitou especificamente o uso dedecltype(auto)
.auto lookup_a_string() { ... }
? É sempre um tipo sem referência? E, portanto,auto lookup_a_string() ->decltype(auto) { ... }
é necessário forçar para permitir que as referências sejam (em alguns casos) retornadas?auto
é definida em termos de modelo de passagem por valor, portanto, sim, não pode ser uma referência. Aguarde por favorauto
pode ser qualquer coisa, incluindo uma referência, é claro.std::vector
. Diga que você temtemplate<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }
. Em seguidaS<bool>::operator[]
, retornará uma referência pendente devido à especialização destd::vector<bool>
. Alterar o tipo de retorno paradecltype(auto)
contornar esse problema.