Quelles sont les raisons de l'existence de std::decay
? Dans quelles situations est-il std::decay
utile?
c++
c++11
standard-library
Eric Javier Hernandez Saura
la source
la source
decay_t<decltype(...)>
est une belle combinaison, pour voir ce que l'auto
on en déduit.Réponses:
<joke> Il est évidemment utilisé pour décomposer les
std::atomic
types radioactifs en types non radioactifs. </joke>N2609 est le papier qui a proposé
std::decay
. Le papier explique:L'exemple motivant est C ++ 03
std::make_pair
:qui a accepté ses paramètres par valeur pour faire fonctionner les littéraux de chaîne:
S'il a accepté ses paramètres par référence, alors
T1
sera déduit comme un type de tableau, puis la construction de apair<T1, T2>
sera mal formée.Mais cela conduit évidemment à des inefficacités significatives. D'où la nécessité
decay
, d'appliquer l'ensemble des transformations qui se produisent lorsque le passage par valeur se produit, vous permettant d'obtenir l'efficacité de prendre les paramètres par référence, tout en obtenant les transformations de type nécessaires pour que votre code fonctionne avec des littéraux de chaîne, types de tableaux, types de fonctions et autres:Remarque: ce n'est pas l'
make_pair
implémentation réelle de C ++ 11 - le C ++ 11make_pair
déballe égalementstd::reference_wrapper
s.la source
Lorsque vous traitez avec des fonctions de modèle qui prennent des paramètres d'un type de modèle, vous avez souvent des paramètres universels. Les paramètres universels sont presque toujours des références d'une sorte ou d'une autre. Ils sont également qualifiés pour la volatilité constante. En tant que tel, la plupart des traits de type ne fonctionnent pas sur eux comme vous vous en doutez:
http://coliru.stacked-crooked.com/a/24476e60bd906bed
La solution ici est d'utiliser
std::decay
:http://coliru.stacked-crooked.com/a/8cbd0119a28a18bd
la source
decay
est très agressif, par exemple s'il est appliqué à une référence à un tableau, il produit un pointeur. Il est généralement trop agressif pour ce type de métaprogrammation à mon humble avis.remove_const_t< remove_reference_t<T> >
, éventuellement enveloppé dans une métafonction personnalisée.