Quelles sont les raisons de l'existence de std::decay
? Dans quelles situations std::decay
est-il utile?Qu'est-ce que std :: decay et quand faut-il l'utiliser?
Répondre
<blague> Il est évidemment utilisé pour se désintégrer radioactif std::atomic
types dans les non-radioactifs. </blague >
N2609 est le papier qui a proposé std::decay
. Le document explique:
Autrement dit,
decay<T>::type
est du type à transformation ayant une identité sauf si T est un type tableau ou une référence à un type de fonction. Dans les cas , ledecay<T>::type
donne respectivement un pointeur ou un pointeur sur une fonction, .
L'exemple motivant est C++ 03 std::make_pair
:
template <class T1, class T2>
inline pair<T1,T2> make_pair(T1 x, T2 y)
{
return pair<T1,T2>(x, y);
}
qui a accepté ses paramètres par valeur pour faire des chaînes littérales travail:
std::pair<std::string, int> p = make_pair("foo", 0);
Si elle a accepté ses paramètres par référence, alors T1
sera déduit comme un type de tableau, puis la construction d'un pair<T1, T2>
sera mal formé. Mais, évidemment, cela conduit à des inefficacités significatives. D'où la nécessité de decay
, d'appliquer l'ensemble des transformations qui se produisent lorsque la valeur de passe se produit, vous permettant d'obtenir l'efficacité de prendre les paramètres par référence, mais obtenez toujours les transformations de type nécessaires pour que votre code fonctionne avec des littéraux de chaîne , les types de tableaux, les types de fonctions et similaires:
template <class T1, class T2>
inline pair< typename decay<T1>::type, typename decay<T2>::type >
make_pair(T1&& x, T2&& y)
{
return pair< typename decay<T1>::type,
typename decay<T2>::type >(std::forward<T1>(x),
std::forward<T2>(y));
}
Note: ce n'est pas réelle C++ 11 make_pair
mise en œuvre - 11 C++ make_pair
aussi unwraps std::reference_wrapper
s.
quelque peu liée: déclinaison en pointeur de tableaux dans C. – Alex
"T1 sera déduit comme un type de tableau, puis la construction d'une paire
Je comprends, de cette façon, nous obtiendrons la paire
Lorsque vous manipulez 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 de const-volatile. En tant que tel, la plupart des caractères de type ne fonctionnent pas sur eux comme on pouvait s'y attendre:
template<class T>
void func(T&& param) {
if (std::is_same<T,int>::value)
std::cout << "param is an int\n";
else
std::cout << "param is not an int\n";
}
int main() {
int three = 3;
func(three); //prints "param is not an int"!!!!
}
http://coliru.stacked-crooked.com/a/24476e60bd906bed
La solution est ici pour utiliser std::decay
:
template<class T>
void func(T&& param) {
if (std::is_same<typename std::decay<T>::type,int>::value)
std::cout << "param is an int\n";
else
std::cout << "param is not an int\n";
}
Je ne suis pas content de ça. 'decay' est très agressif, par exemple s'il est appliqué à une référence à tableau il donne un pointeur.Il est généralement trop agressif pour ce genre de métaprogrammation IMHO – dyp
@dyp, quoi de moins "agressif" alors? Quelles sont les alternatives? –
@SergeRogatch Dans le cas de "paramètres universels"/références universelles/renvois, je supprimerais simplement 'remove_const_t
- 1. En C++ 11, quand devrions-nous utiliser explicitement std :: decay?
- 2. Est-ce logique de spécialiser std :: decay?
- 3. Quand est-ce que j'utilise std :: random_device?
- 4. JS Physics Acceleration Decay
- 5. Comment utiliser std :: decay lors de la spécialisation partielle d'un trait de type?
- 6. Javascript/jquery fade effect decay
- 7. Elasticsearch date decay fonction, Rails
- 8. Quand et comment utiliser std :: locale :: messages?
- 9. Quand utiliser std :: async vs std :: threads?
- 10. Quand est-ce que std :: string_view :: operator == vraiment constexpr?
- 11. C + 11-Like Type Decay dans Rust
- 12. Est-ce que std :: stack et std :: queue sont compatibles?
- 13. T-SQL Row par Row Decay
- 14. Quand est std :: chrono époque?
- 15. C++ quand et comment std :: itérateur type_valeur, référence, pointeur utilisé?
- 16. std :: vecteur plus rapide que std :: unordered_set?
- 17. Que fait la méthode _Get d'un std :: weak_ptr et quand devrait-elle être utilisée?
- 18. Pourquoi `std :: common_type_t <std :: ostream &, std :: ostream &>` est-il égal à `std :: ostream` et non` std :: ostream & `?
- 19. Quand utiliser Eigen :: Vector vs std :: vector?
- 20. Quand devrait-on utiliser std :: atomic_compare_exchange_strong?
- 21. std :: fusion ne fonctionne pas avec std :: async
- 22. Différence entre std :: logical_not et std :: not1?
- 23. Que fait std :: _ lockit?
- 24. entrée python std seulement quand je veux
- 25. Quand devrions-nous utiliser std :: enable_shared_from_this
- 26. Quand std :: sort arrête la comparaison
- 27. Quand remplacer std :: unique_ptr par un singleton
- 28. quand utiliser Deleter personnalisé pour std :: shared_ptr
- 29. std :: atomic_flag et std :: lock_guard
- 30. Pourquoi std :: sort() est-il plus rapide que std :: make_heap()?
Il est utilisé dans la bibliothèque standard, par ex. lors de la transmission d'arguments à un thread. Ceux-ci doivent être * stockés *, en valeur, de sorte que vous ne puissiez pas les stocker, par ex. tableaux. Au lieu de cela, un pointeur est stocké et ainsi de suite. C'est aussi une métafonction qui imite les ajustements de type de paramètre de fonction. – dyp
'decay_t' est une bonne combinaison, pour voir ce que 'auto' pourrait en déduire. –
[meta.trans.other] états: Ce comportement est similaire à [...= Plusieurs] conversions appliquées lorsqu'une expression lvalue est utilisé comme rvalue, mais aussi des bandes cv-qualifiés de types de classe ** pour de modèle plus près par valeur ** passage d 'arguments. » – dyp