หากคุณต้องการประเภทของสิ่งที่ไม่ใช่การเรียกใช้ฟังก์ชันstd::result_ofก็ไม่ต้องใช้ decltype()สามารถระบุประเภทของนิพจน์ใดก็ได้
หากเรา จำกัด ตัวเองเพียงวิธีต่างๆในการกำหนดประเภทการส่งคืนของการเรียกใช้ฟังก์ชัน (ระหว่างstd::result_of_t<F(Args...)>และdecltype(std::declval<F>()(std::declval<Args>()...)) ก็จะมีความแตกต่าง
std::result_of<F(Args...) ถูกกำหนดให้เป็น:
ถ้านิพจน์
INVOKE (declval<Fn>(), declval<ArgTypes>()...)ถูกสร้างขึ้นอย่างดีเมื่อถือว่าเป็นตัวถูกดำเนินการที่ไม่ได้ประเมิน (ข้อ 5) ประเภทสมาชิกจะตั้งชื่อประเภทเป็นdecltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));
อย่างอื่นจะไม่มีประเภทสมาชิก
ความแตกต่างระหว่างresult_of<F(Args..)>::typeและdecltype(std::declval<F>()(std::declval<Args>()...)เป็นข้อมูลเกี่ยวกับสิ่งINVOKEนั้น การใช้declval/ decltypeโดยตรงนอกจากจะพิมพ์ได้นานขึ้นเล็กน้อยแล้วจะใช้ได้Fก็ต่อเมื่อสามารถเรียกใช้ได้โดยตรงเท่านั้น (ประเภทอ็อบเจ็กต์ฟังก์ชันหรือฟังก์ชันหรือตัวชี้ฟังก์ชัน) result_ofนอกจากนี้ยังสนับสนุนตัวชี้ไปยังฟังก์ชันสมาชิกและตัวชี้ไปยังข้อมูลสมาชิก
ในขั้นต้นการใช้declval/ decltypeรับประกันนิพจน์ที่เป็นมิตรกับ SFINAE ในขณะที่std::result_ofอาจทำให้คุณเกิดข้อผิดพลาดอย่างหนักแทนการหักล้มเหลว ที่ได้รับการแก้ไขใน C ++ 14: std::result_ofตอนนี้จำเป็นต้องเป็นมิตรกับ SFINAE (ขอบคุณเอกสารนี้ )
ดังนั้นในคอมไพเลอร์ C ++ 14 ที่สอดคล้องกันstd::result_of_t<F(Args...)>นั้นเหนือกว่าอย่างเคร่งครัด มันชัดเจนสั้นและถูกต้อง†สนับสนุนเพิ่มเติมFs ‡
†เว้นแต่ว่าคุณกำลังใช้มันในบริบทที่คุณไม่ต้องการให้ตัวชี้แก่สมาชิกดังนั้น
std::result_of_tจะประสบความสำเร็จในกรณีที่คุณอาจต้องการให้มันล้มเหลว
‡มีข้อยกเว้น ในขณะที่มันสนับสนุนตัวชี้ไปยังสมาชิกresult_ofจะไม่ทำงานหากคุณพยายามที่จะยกตัวอย่างที่ไม่ถูกต้องประเภท-ID สิ่งเหล่านี้จะรวมถึงฟังก์ชันที่ส่งคืนฟังก์ชันหรือประเภทนามธรรมตามค่า เช่น:
template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }
int answer() { return 42; }
call(answer); // nope
การใช้งานที่ถูกต้องจะได้รับแต่นั่นคือรายละเอียดที่คุณไม่ต้องจำไว้ด้วยresult_of_t<F&()>decltype
decltypeนั้นน่าเกลียดกว่า แต่ก็มีพลังมากกว่าด้วยresult_ofสามารถใช้ได้เฉพาะกับประเภทที่เรียกได้และต้องใช้ประเภทเป็นอาร์กิวเมนต์ ตัวอย่างเช่นคุณไม่สามารถใช้result_ofที่นี่:template <typename T, typename U> auto sum( T t, U u ) -> decltype( t + u );ถ้าอาร์กิวเมนต์สามารถเป็นประเภทเลขคณิตได้ (ไม่มีฟังก์ชันFที่คุณสามารถกำหนดF(T,U)ให้เป็นตัวแทนt+uได้สำหรับประเภทที่ผู้ใช้กำหนดคุณสามารถทำได้ในทำนองเดียวกัน (ฉันไม่ได้เล่นด้วยจริงๆ) ฉันคิดว่า การโทรไปยังเมธอดสมาชิกอาจทำได้ยากresult_ofโดยไม่ต้องใช้สารยึดเกาะหรือ