std::decay
'un nedenleri nelerdir? std::decay
hangi durumlarda kullanışlıdır?std :: decay nedir ve ne zaman kullanılmalıdır?
cevap
< şaka > Açıkça radyoaktifçürümesi için kullanılır Radyoaktif olmayanlaratipi. </şaka >
N2609std::decay
önerilen kağıttır. Kağıt açıklar: burada T bir dizi türü ya da bir fonksiyon tipi için bir başvuru ise
,
decay<T>::type
dışında kimlik tip bir dönüşümdür. Bu vakalarındadecay<T>::type
, sırasıyla işlevine bir işaretçi veya işaretçi verir. ,std::pair<std::string, int> p = make_pair("foo", 0);
o referans parametrelerini kabul ettiyse:
dize hazır çalışması için değerine göre parametrelerini kabul hangi:template <class T1, class T2> inline pair<T1,T2> make_pair(T1 x, T2 y) { return pair<T1,T2>(x, y); }
motive örnek C++ 03 std::make_pair
olduğunu daha sonra T1
bir dizi tipi olarak çıkarılacak ve daha sonra bir pair<T1, T2>
yapı bozuk olacak.
Ancak açıkçası bu önemli verimsizliklere yol açmaktadır. Bu nedenle, değer aktarımı gerçekleştiğinde ortaya çıkan dönüştürme setini uygulamak için decay
'a gereksinim duymak, böylece parametreleri referans alarak alma verimliliğini elde etmenize izin verir, ancak kodunuz için dizgi değişmezleriyle çalışmak için gereken tür dönüşümlerini elde edebilirsiniz. , dizi tipleri, fonksiyon türleri ve benzerleri gibi:
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));
}
Not: Bu gerçek C++ 11 make_pair
uygulama değil - C++ 11 make_pair
da std::reference_wrapper
s deriyi açar.
Şablon türü parametrelerini alan şablon işlevleriyle uğraşırken, genellikle evrensel parametrelere sahipsiniz. Evrensel parametreler hemen hemen her zaman bir çeşit referanstır. Aynı zamanda kalifiye uçucu niteliktedirler. Beklediğiniz gibi gibi, çoğu yapı özellikleri üzerlerinde çalışmaz:
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
burada çözüm kullanmaktır 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";
}
Bundan memnun değilim. "çürüme" çok agresiftir; bir işaretçi verir dizisi.Bu genellikle bu tür metaprogramlama IMHO için çok agresiftir – dyp
@dyp, ne daha az "agresif" o zaman? Alternatifler nelerdir? –
@SergeRogatch "Evrensel parametreler"/evrensel referanslar/yönlendirme referansları olması durumunda, muhtemelen özel bir meta işleve sarılmış olan remove_const_t
Standart kütüphanede örn. argümanları bir thread'a geçirirken. Bu değerlerin * depolanması *, değere göre, yani saklayamazsınız. diziler. Bunun yerine, bir işaretçi saklanır ve böyle devam eder. Aynı zamanda işlev parametre türü ayarlamalarını taklit eden bir işlevdir. – dyp
'decay_t' auto'nun ne olacağını görmek için hoş bir kombinasyon. –
[meta.trans.other] durumlar: Bu davranışı [...= Birkaç] bir lvalue ifade bir rvalue olarak kullanıldığı zaman uygulanabilir ancak daha yakın yan değer argüman geçen ** modellenmesi için sınıf türleri ** den ev-eleme şeritleri." – dyp