Varlığının nedenleri nelerdir std::decay
? Hangi durumlarda std::decay
faydalıdır?
decay_t<decltype(...)>
neyin ortaya auto
çıkacağını görmek için güzel bir kombinasyon .
Varlığının nedenleri nelerdir std::decay
? Hangi durumlarda std::decay
faydalıdır?
decay_t<decltype(...)>
neyin ortaya auto
çıkacağını görmek için güzel bir kombinasyon .
Yanıtlar:
<joke> Açıkça radyoaktif std::atomic
türleri radyoaktif olmayan türlere bozmak için kullanılır . </joke>
N2609 önerilen makaledirstd::decay
. Makale açıklıyor:
Basitçe ifade etmek gerekirse,
decay<T>::type
T bir dizi tipi ya da bir fonksiyon tipine referans olması dışında kimlik tipi-dönüşümdür. Bu durumlarda,decay<T>::type
bir işleve sırasıyla bir işaretçi veya işaretçi verir.
Motive edici örnek C ++ 03'tür std::make_pair
:
template <class T1, class T2>
inline pair<T1,T2> make_pair(T1 x, T2 y)
{
return pair<T1,T2>(x, y);
}
dize değişmez değerlerini çalıştırmak için parametrelerini değere göre kabul eden:
std::pair<std::string, int> p = make_pair("foo", 0);
Eğer parametrelerini referans olarak kabul ederse, o T1
zaman bir dizi tipi olarak çıkartılacak ve daha sonra pair<T1, T2>
a'nın oluşturulması yanlış oluşturulacaktır.
Ancak bu açıkça önemli verimsizliklere yol açıyor. Bu nedenle, decay
pass-by-value meydana geldiğinde oluşan dönüşümler kümesini uygulama gereği , parametreleri referans alarak alma verimliliğini elde etmenizi sağlar, ancak yine de kodunuzun dize değişmezleriyle çalışması için gereken tip dönüşümlerini elde etmenizi sağlar, dizi türleri, işlev türleri ve benzerleri:
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
uygulaması değildir - C ++ 11 make_pair
de std::reference_wrapper
s.
Bir şablon türündeki parametreleri alan şablon işlevleriyle uğraşırken, genellikle evrensel parametreleriniz olur. Evrensel parametreler hemen hemen her zaman bir veya daha fazla referanstır. Aynı zamanda kalıcı niteliklidir. Bu nedenle, çoğu tür özelliği beklediğiniz gibi ç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
Buradaki çö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";
}
decay
çok agresiftir, örneğin diziye bir referansa uygulanırsa bir işaretçi verir. Bu tür bir metaprogramlama IMHO'su için genellikle çok agresiftir.
remove_const_t< remove_reference_t<T> >
özel bir metafonksiyona sarılırdım.