2014-09-08 28 views
120

std::decay'un nedenleri nelerdir? std::decay hangi durumlarda kullanışlıdır?std :: decay nedir ve ne zaman kullanılmalıdır?

+3

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

+3

'decay_t ' auto'nun ne olacağını görmek için hoş bir kombinasyon. –

+0

[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

cevap

116

< ş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

Basitçe

, decay<T>::type dışında kimlik tip bir dönüşümdür. Bu vakalarında decay<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:

template <class T1, class T2> 
inline pair<T1,T2> make_pair(T1 x, T2 y) 
{ 
    return pair<T1,T2>(x, y); 
} 

dize hazır çalışması için değerine göre parametrelerini kabul hangi:

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.

+0

biraz ilgili: C. dizisinde işaretçi çürütmesi için – Alex

+0

"T1 bir dizi türü olarak çıkarılacaktır ve daha sonra bir çift oluşturmak yaramaz olacaktır." Burada sorun nedir? – camino

+3

Anladım, bu şekilde sadece 4 karakterli çiftini kabul edebiliyoruz – camino

43

Ş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"; 
} 

http://coliru.stacked-crooked.com/a/8cbd0119a28a18bd

+12

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

+0

@dyp, ne daha az "agresif" o zaman? Alternatifler nelerdir? –

+2

@SergeRogatch "Evrensel parametreler"/evrensel referanslar/yönlendirme referansları olması durumunda, muhtemelen özel bir meta işleve sarılmış olan remove_const_t > 'yi kullanırdım. – dyp

İlgili konular