คำจำกัดความที่น่าสงสัยของ common_type

ในหนังสือ "The Cpp Standard Library" ฉบับพิมพ์ครั้งที่ 2 โดย Nicolai M. Josuttis กล่าวไว้ (5.4, หน้า 125) ว่าคำจำกัดความของประเภททั่วไปของ struct มีดังนี้:

template <typename T1, typename T2>
struct common_type<T1,T2> {
typedef decltype(true ? declval<T1>() : declval<T2>()) type;
};

ฉันมีปัญหาร้ายแรงที่จะเชื่อว่านี่เป็นคำจำกัดความที่ถูกต้องของ common_type เหตุผล:

typedef decltype(true ? declval<T1>() : declval<T2>()) type;//As far as I understand this will always pick second operand, declval<T1>(), due to the fact that there is 'true' value. Am I right?

person smallB    schedule 07.11.2012    source แหล่งที่มา
comment
นิพจน์ไม่ได้รับการประเมินจริง ๆ เพียงใช้ประเภทจากนิพจน์นั้น   -  person Some programmer dude    schedule 07.11.2012
comment
@JoachimPileborg ใช่ฉันเข้าใจแล้ว แต่ ternary ?: จะส่งคืนตัวถูกดำเนินการทางด้านซ้ายมือของ ':' เสมอหากค่าที่อยู่ข้างหน้า '?' เป็นความจริง.   -  person smallB    schedule 07.11.2012
comment
หากอาจเป็น false เช่นกัน เนื่องจากโค้ดไม่เคยทำงาน เป็นไปได้มากว่าไม่มีแม้แต่รหัสใด ๆ ที่สร้างขึ้นสำหรับสิ่งนี้ แม้กระทั่งข้อผิดพลาดที่จะมี std::declval ในโค้ดที่ถูกดำเนินการ   -  person Some programmer dude    schedule 07.11.2012
comment
โปรดทราบว่าแม้ว่าสิ่งนี้จะได้รับการประเมิน (ซึ่งไม่ใช่) นิพจน์ตัวดำเนินการแบบไตรภาคจะไม่มีประเภทของตัวถูกดำเนินการที่ส่งคืนโดยอัตโนมัติ เนื่องจากจะทราบเฉพาะที่รันไทม์เท่านั้น (แม้ว่าในกรณีนี้เงื่อนไขจะเป็นดังนี้) ค่าคงที่เวลาคอมไพล์ แต่นั่นเป็นเพียงกรณีพิเศษ) ดังนั้นมันจึงต้องเป็นประเภททั่วไปของตัวถูกดำเนินการทั้งสองตัว จึงจะทราบประเภทนั้นในเวลาคอมไพล์   -  person Christian Rau    schedule 07.11.2012
comment
รายละเอียด: คำจำกัดความของ common_type นี้ส่งผลให้เกิดพฤติกรรมที่ไม่ได้ตั้งใจในบางกรณี ดูที่ รายงานข้อบกพร่อง DR2142 แต่คำตอบของ Eugene Mamin ยังคงถูกต้อง   -  person dyp    schedule 08.11.2012


คำตอบ (1)


มันคือทั้งหมดที่เกี่ยวกับตัวดำเนินการแบบมีเงื่อนไข ไม่ใช่คำสั่งการเลือก เช่น if หรือ switch

ย่อหน้า 5.16 ของมาตรฐาน ISO C++11:

มิฉะนั้น หากตัวถูกดำเนินการตัวที่สองและตัวที่สามมีประเภทที่แตกต่างกันและมีประเภทคลาส (อาจผ่านคุณสมบัติ CV) หรือหากทั้งคู่เป็นค่า gl ของหมวดหมู่ค่าเดียวกันและเป็นประเภทเดียวกัน ยกเว้นคุณสมบัติ CV จะมีความพยายามในการแปลงแต่ละรายการ ของตัวถูกดำเนินการเหล่านั้นไปเป็นประเภทอื่น

ดังนั้น มันไม่สำคัญว่า decltype จะมีเงื่อนไขจริง คอมไพเลอร์จะต้องเลือกประเภททั่วไปตามผลลัพธ์

UPD: 5.16 มีคำอธิบายเพิ่มเติมเกี่ยวกับพฤติกรรมที่ถูกต้อง คุณควรดูเพื่อทำความเข้าใจกระบวนการทั้งหมดโดยสมบูรณ์ แต่สำหรับคำถามเฉพาะของคุณ:

เมื่อใช้กระบวนการนี้ จะพิจารณาว่าสามารถแปลงตัวถูกดำเนินการตัวที่สองให้ตรงกับตัวถูกดำเนินการตัวที่สามได้หรือไม่ และจะสามารถแปลงตัวถูกดำเนินการตัวที่สามให้ตรงกับตัวถูกดำเนินการตัวที่สองได้หรือไม่ หากสามารถแปลงทั้งสองรายการได้ หรือแปลงรายการใดรายการหนึ่งได้แต่การแปลงไม่ชัดเจน แสดงว่าโปรแกรมมีรูปแบบไม่ถูกต้อง หากไม่สามารถแปลงทั้งสองรายการได้ ตัวถูกดำเนินการจะไม่เปลี่ยนแปลงและดำเนินการตรวจสอบเพิ่มเติมตามที่อธิบายไว้ด้านล่าง หากเป็นไปได้ว่ามีการแปลงเพียงครั้งเดียว การแปลงนั้นจะถูกนำไปใช้กับตัวถูกดำเนินการที่เลือก และตัวถูกดำเนินการที่แปลงแล้วจะถูกใช้แทนตัวถูกดำเนินการดั้งเดิมสำหรับส่วนที่เหลือของส่วนนี้

person Eugene Mamin    schedule 07.11.2012
comment
สวัสดี ขอบคุณสำหรับคำตอบ ปัญหาเดียวที่ฉันมีคือ: มีการพยายามแปลงตัวถูกดำเนินการแต่ละรายการไปเป็นประเภทอื่น มันจะทำงานอย่างไร? คอมไพเลอร์กำลังแปลงประเภทของตัวถูกดำเนินการทางซ้ายไปเป็นประเภททางขวาหรือในทางกลับกันหรือไม่? มีกฎเกณฑ์อะไรบ้าง? - person smallB; 07.11.2012