Quais são as razões da existência de std::decay
? Em que situações é std::decay
útil?
c++
c++11
standard-library
Eric Javier Hernandez Saura
fonte
fonte
decay_t<decltype(...)>
é uma boa combinação, para ver oauto
que deduziria.Respostas:
<joke> Obviamente, é usado para decompor
std::atomic
tipos radioativos em não-radioativos. </joke>N2609 é o documento que propôs
std::decay
. O artigo explica:O exemplo motivador é C ++ 03
std::make_pair
:que aceitou seus parâmetros por valor para fazer literais de string funcionarem:
Se ele aceitou seus parâmetros por referência,
T1
será deduzido como um tipo de matriz e, em seguida, a construção de umpair<T1, T2>
será mal formada.Mas, obviamente, isso leva a ineficiências significativas. Daí a necessidade de
decay
, aplicar o conjunto de transformações que ocorre quando passa por valor, permitindo obter a eficiência de obter os parâmetros por referência, mas ainda assim obter as transformações de tipo necessárias para que seu código funcione com literais de string, tipos de matriz, tipos de função e similares:Nota: essa não é a
make_pair
implementação real do C ++ 11 - o C ++ 11make_pair
também desembrulhastd::reference_wrapper
s.fonte
Ao lidar com funções de modelo que usam parâmetros de um tipo de modelo, você geralmente possui parâmetros universais. Parâmetros universais são quase sempre referências de um tipo ou de outro. Eles também são qualificados como voláteis. Como tal, a maioria dos traços de tipo não funciona neles conforme o esperado:
http://coliru.stacked-crooked.com/a/24476e60bd906bed
A solução aqui é usar
std::decay
:http://coliru.stacked-crooked.com/a/8cbd0119a28a18bd
fonte
decay
é muito agressivo, por exemplo, se aplicado a uma referência ao array, gera um ponteiro. É tipicamente agressivo demais para esse tipo de meta-programação IMHO.remove_const_t< remove_reference_t<T> >
, possivelmente, envolvido em uma metafunção personalizada.