อะไรคือสาเหตุของการมีอยู่ของstd::decay
? ในสถานการณ์ใดที่std::decay
มีประโยชน์?
decay_t<decltype(...)>
เป็นการผสมผสานที่ดีเพื่อดูว่าอะไรauto
จะอนุมาน
อะไรคือสาเหตุของการมีอยู่ของstd::decay
? ในสถานการณ์ใดที่std::decay
มีประโยชน์?
decay_t<decltype(...)>
เป็นการผสมผสานที่ดีเพื่อดูว่าอะไรauto
จะอนุมาน
คำตอบ:
<โจ๊ก> เห็นได้ชัดว่ามันใช้เพื่อสลายstd::atomic
ประเภทกัมมันตภาพรังสีให้กลายเป็นประเภทที่ไม่มีกัมมันตภาพรังสี </joke>
N2609std::decay
เป็นกระดาษที่นำเสนอ กระดาษอธิบาย:
พูดง่ายๆ
decay<T>::type
คือการแปลงชนิดข้อมูลเฉพาะตัวยกเว้นว่า T เป็นประเภทอาร์เรย์หรือการอ้างอิงถึงประเภทฟังก์ชัน ในกรณีเหล่านั้นdecay<T>::type
ให้ตัวชี้หรือตัวชี้ไปยังฟังก์ชั่นตามลำดับ
ตัวอย่างแรงจูงใจคือ 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);
}
ซึ่งยอมรับพารามิเตอร์ด้วยค่าเพื่อให้ตัวอักษรสตริงทำงาน:
std::pair<std::string, int> p = make_pair("foo", 0);
ถ้ามันยอมรับพารามิเตอร์โดยอ้างอิงแล้วT1
จะถูกหักเป็นประเภทอาร์เรย์และจากนั้นการสร้างpair<T1, T2>
จะเป็นรูปแบบที่ไม่ดี
แต่เห็นได้ชัดว่าสิ่งนี้นำไปสู่การไร้ประสิทธิภาพที่สำคัญ ดังนั้นความจำเป็นในdecay
การใช้ชุดการแปลงที่เกิดขึ้นเมื่อค่า pass-by-value เกิดขึ้นช่วยให้คุณได้รับประสิทธิภาพของการอ้างอิงพารามิเตอร์ แต่ยังได้รับการแปลงชนิดที่จำเป็นสำหรับรหัสของคุณเพื่อทำงานกับตัวอักษรสตริง ประเภทอาร์เรย์ประเภทฟังก์ชั่นและสิ่งที่ชอบ:
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));
}
หมายเหตุ:นี่ไม่ใช่การนำ C ++ 11 make_pair
ไปใช้จริง - C ++ 11 make_pair
ยังไม่std::reference_wrapper
ได้แยกออก
เมื่อจัดการกับฟังก์ชั่นเทมเพลตที่รับพารามิเตอร์ของประเภทเทมเพลตคุณมักจะมีพารามิเตอร์สากล พารามิเตอร์สากลนั้นมักจะมีการอ้างอิงถึงการเรียงลำดับอย่างใดอย่างหนึ่ง พวกมันยังมีคุณสมบัติในการระเหยง่าย ดังนั้นคุณลักษณะส่วนใหญ่จะไม่ทำงานตามที่คุณคาดหวัง:
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
ทางออกที่นี่คือการใช้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
มีความก้าวร้าวมากเช่นถ้านำไปใช้กับการอ้างอิงถึงอาร์เรย์จะให้ตัวชี้ โดยทั่วไปแล้วจะมีความก้าวร้าวเกินกว่าที่ IMHO ประเภทนี้จะใช้ในการเปรียบเทียบ
remove_const_t< remove_reference_t<T> >
จะห่อด้วยเมตาฟังก์ชั่นที่กำหนดเอง