Quali sono i motivi dell'esistenza di std::decay
? In quali situazioni è utile std::decay
?Che cos'è std :: decay e quando dovrebbe essere usato?
risposta
<joke> È ovviamente usato per decadere radioattivo std::atomic
tipi in tipi non radioattivi. </scherzo >
N2609 è la carta che ha proposto std::decay
. Il documento spiega:
poche parole,
decay<T>::type
è l'identità del tipo di trasformazione tranne se T è un tipo di matrice o un riferimento ad un tipo di funzione. Nei casi ildecay<T>::type
produce rispettivamente un puntatore o un puntatore a una funzione, .
L'esempio motivante è 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);
}
che accettano i parametri al valore per rendere letterali stringa funzionano:
std::pair<std::string, int> p = make_pair("foo", 0);
Se accettato i parametri per riferimento, quindi T1
verrà dedotto come un tipo di matrice e quindi la costruzione di un pair<T1, T2>
sarà mal formata.
Ma ovviamente questo porta a notevoli inefficienze. Da qui la necessità di decay
, di applicare il set di trasformazioni che si verifica quando si verifica il pass-by-value, consentendo di ottenere l'efficienza di prendere i parametri per riferimento, ma ottenere comunque le trasformazioni di tipo necessarie affinché il codice funzioni con stringhe letterali , tipi di array, tipi di funzione e simili:
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));
}
Nota: questo non è l'effettiva implementazione C++ 11 make_pair
- C++ 11 make_pair
scarta anche std::reference_wrapper
s.
in qualche modo correlato: decadimento del puntatore di matrici in C. – Alex
"T1 verrà dedotto come un tipo di matrice e quindi la costruzione di una coppia
Ho capito, in questo modo otterremo la coppia
Quando si ha a che fare con funzioni di modello che utilizzano parametri di un tipo di modello, spesso si hanno parametri universali. I parametri universali sono quasi sempre riferimenti di un tipo o dell'altro. Sono anche qualificati instabili. Come tale, la maggior parte delle caratteristiche di tipo non funzionano su di loro come ci si aspetterebbe:
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 soluzione è quella di utilizzare 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";
}
Non sono contento di questo. 'decay' è molto aggressivo, ad esempio se applicato a un riferimento a array produce un puntatore, tipicamente troppo aggressivo per questo tipo di metaprogrammazione IMHO – dyp
@dyp, cosa c'è di meno "aggressivo" allora? Quali sono le alternative? –
@SergeRogatch Nel caso di "parametri universali"/riferimenti universali/riferimenti di inoltro, vorrei semplicemente 'remove_const_t
- 1. Quando dovrebbe essere usato std :: atomic_compare_exchange_strong?
- 2. Dovrebbe essere sempre usato std :: endl?
- 3. Che cosa fa '@reify' e quando dovrebbe essere usato?
- 4. Quando dovrebbe essere usato un memoryview?
- 5. Intestazione E-Mail: Versione MIME: 1.0 - Quando dovrebbe essere usato?
- 6. Cosa fa python sys.intern e quando dovrebbe essere usato?
- 7. dovrebbe mai essere usato encodeURI?
- 8. Quando "dev-master" dovrebbe essere usato in composit.json?
- 9. NSInteger dovrebbe essere usato davvero ovunque?
- 10. Che cosa dovrebbe essere usato per verificare l'identità in C++?
- 11. Dovrebbe essere std :: atomic volatile?
- 12. Dovrebbe essere usato `! Var` o` var == NULL`?
- 13. Quando initWithFormat: argomenti: essere usato?
- 14. Quando deve essere usato assert()?
- 15. Per cosa può essere usato std :: remove_extent?
- 16. Dovrebbe essere std :: move drop constness?
- 17. Dovrebbe essere usato instancetype sui metodi alloc/new/init?
- 18. Quale specificatore di formato dovrebbe essere usato per BOOL?
- 19. Come affermare che C++ 11 dovrebbe essere usato per compilare il mio programma?
- 20. Perché dovrebbe essere usato Homebrew per installare Python?
- 21. GWT - dovrebbe essere usato solo per le parti dinamiche?
- 22. Quando dovrebbe essere una classe .NET Override()? Quando non dovrebbe?
- 23. Arguments.callee è deprecato - cosa dovrebbe invece essere usato?
- 24. Dovrebbe essere usato esattamente IAppBuilder.CreatePerOwinContext <T>?
- 25. Hibernate EntityManager, dovrebbe essere usato come un singleton?
- 26. Che cosa dovrebbe essere compressionuality quando si utilizza UIImageJPEGRepresentation?
- 27. webHttp Vs enableWebScript, che dovrebbe essere usato per la richiesta POST REST WCF?
- 28. Dovrebbe essere usato `propTypes` e` defaultProps` in combinazione con Flowtype, o Flowtype è abbastanza completo?
- 29. ModelState.IsValid anche quando non dovrebbe essere?
- 30. & o & cosa dovrebbe essere usato per & (e commerciale) se usiamo utf8 nel documento xhtml?
Viene utilizzato nella libreria standard ad es. quando si passano argomenti a un thread. Questi devono essere * memorizzati *, in base al valore, quindi non è possibile memorizzare ad es. array. Invece, un puntatore viene memorizzato e così via. È anche una metafunzione che simula le regolazioni del tipo di parametro della funzione. – dyp
'decay_t' è una bella combinazione, per vedere cosa dedurrebbe 'auto'. –
[meta.trans.other] afferma: Questo comportamento è simile al [...= Vari] conversioni applicata quando un'espressione lvalue è utilizzato come rvalue, ma anche strisce CV-qualificazioni da tipi di classe ** al fine modellare più strettamente per valore argomento passando **." – dyp