Apa alasan keberadaannya std::decay
? Dalam situasi apa std::decay
berguna?
decay_t<decltype(...)>
adalah kombinasi yang bagus, untuk melihat apa yang auto
akan disimpulkan.
Apa alasan keberadaannya std::decay
? Dalam situasi apa std::decay
berguna?
decay_t<decltype(...)>
adalah kombinasi yang bagus, untuk melihat apa yang auto
akan disimpulkan.
Jawaban:
<canda> Ini jelas digunakan untuk meluruhkan std::atomic
tipe radioaktif menjadi non-radioaktif. </joke>
N2609 adalah makalah yang diusulkan std::decay
. Makalah ini menjelaskan:
Sederhananya,
decay<T>::type
adalah tipe-transformasi kecuali jika T adalah tipe array atau referensi ke tipe fungsi. Dalam kasus tersebutdecay<T>::type
, masing-masing menghasilkan penunjuk atau penunjuk ke fungsi.
Contoh yang memotivasi adalah 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);
}
yang menerima parameternya dengan nilai untuk membuat string literal berfungsi:
std::pair<std::string, int> p = make_pair("foo", 0);
Jika ia menerima parameternya dengan referensi, maka T1
akan disimpulkan sebagai tipe array, dan kemudian membangun pair<T1, T2>
akan menjadi salah bentuk.
Tapi jelas ini menyebabkan inefisiensi yang signifikan. Oleh karena itu perlunya decay
, untuk menerapkan serangkaian transformasi yang terjadi ketika nilai demi nilai terjadi, memungkinkan Anda untuk mendapatkan efisiensi dengan mengambil parameter dengan referensi, tetapi masih mendapatkan jenis transformasi yang diperlukan untuk kode Anda untuk bekerja dengan string literal, tipe array, tipe fungsi dan sejenisnya:
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));
}
Catatan: ini bukan make_pair
implementasi C ++ 11 yang sebenarnya - C ++ 11 make_pair
juga membuka std::reference_wrapper
s.
Ketika berhadapan dengan fungsi templat yang mengambil parameter dari tipe templat, Anda sering memiliki parameter universal. Parameter universal hampir selalu merupakan referensi dari satu jenis atau lainnya. Mereka juga memenuhi syarat const-volatile. Dengan demikian, sebagian besar sifat tipe tidak berfungsi seperti yang Anda harapkan:
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
Solusinya di sini adalah menggunakan 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
sangat agresif, misalnya jika diterapkan pada referensi ke array itu menghasilkan pointer. Biasanya terlalu agresif untuk metaprogramming IMHO semacam ini.
remove_const_t< remove_reference_t<T> >
, mungkin dibungkus dengan metafungsi khusus.