ตัวดำเนินการลูกศร (->) ในส่วนหัวของฟังก์ชัน


129

ฉันเจอรหัสต่อไปนี้:

template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) {
   return a+b;
}

มีสิ่งหนึ่งที่ฉันไม่เข้าใจ:

ฉันจะทราบได้อย่างไรว่าตัวดำเนินการลูกศร ( ->) หมายถึงอะไรในส่วนหัวของฟังก์ชัน ฉันเดาด้วยเหตุผลล้วนๆว่า->โอเปอเรเตอร์กำหนดประเภทซึ่งautoจะอนุมานได้ แต่ฉันต้องการตรงนี้ ฉันไม่พบข้อมูลใด ๆ


2
ซึ่งเป็นส่วนหนึ่งของไวยากรณ์ประเภทผลตอบแทนต่อท้าย ดูstackoverflow.com/a/4113390/962089
chris

2
ไม่ใช่ตัวดำเนินการ แต่เป็นส่วนหนึ่งของไวยากรณ์
texasbruce

1
ในคำตอบของ "ฉันจะอ่านได้ที่ไหน" ข้อมูลจำเพาะของ C ++ นั้นน่าเชื่อถือที่สุด หากขาดเงินทุนหรือต้องการใช้จ่าย $$ ร่างการทำงานล่าสุดมักจะใกล้เคียงเพียงพอและไม่มีค่าใช้จ่าย ข้อกำหนดเหล่านี้มีความเชี่ยวชาญสูงดังนั้นจึงขาดความคุ้นเคยในการอ่านข้อกำหนด ISO ให้ลองใช้ cplusplus.com หรือ cppreference.com หรือไซต์อื่น ๆ ที่ไม่น่าเชื่อถือ แต่โดยปกติแล้วจะมีความแม่นยำมาก หมายเหตุ: อาจละเว้นประเภทผลตอบแทนต่อท้ายด้วย C ++ 14
Les

คำตอบ:


206

ใน C ++ 11 มีไวยากรณ์สองแบบสำหรับการประกาศฟังก์ชัน:

    return-type identifier ( การประกาศอาร์กิวเมนต์ ... )

และ

    auto ตัวระบุ ( การประกาศอาร์กิวเมนต์ ... ) -> return_type

พวกเขาเทียบเท่า ตอนนี้เมื่อเทียบเท่าแล้วทำไมคุณถึงต้องการใช้แบบหลัง? C ++ 11 แนะนำdecltypeสิ่งที่ยอดเยี่ยมนี้ซึ่งช่วยให้คุณสามารถอธิบายประเภทของนิพจน์ได้ ดังนั้นคุณอาจต้องการรับประเภทผลตอบแทนจากประเภทอาร์กิวเมนต์ ดังนั้นคุณลอง:

template <typename T1, typename T2>
decltype(a + b) compose(T1 a, T2 b);

และคอมไพเลอร์จะบอกคุณว่ามันไม่รู้aและbอยู่ในdecltypeอาร์กิวเมนต์ นั่นเป็นเพราะพวกเขาประกาศโดยรายการอาร์กิวเมนต์เท่านั้น

คุณสามารถแก้ไขปัญหาได้อย่างง่ายดายโดยใช้declvalและพารามิเตอร์เทมเพลตที่ประกาศไว้แล้ว ชอบ:

template <typename T1, typename T2>
decltype(std::declval<T1>() + std::declval<T2>())
compose(T1 a, T2 b);

ยกเว้นตอนนี้มันดูละเอียดขึ้นจริงๆ ดังนั้นจึงมีการเสนอและใช้ไวยากรณ์การประกาศทางเลือกและตอนนี้คุณสามารถเขียนได้แล้ว

template <typename T1, typename T2>
auto compose(T1 a, T2 b) -> decltype(a + b);

และมันละเอียดน้อยลงและกฎการกำหนดขอบเขตก็ไม่จำเป็นต้องเปลี่ยนแปลง


การอัปเดต C ++ 14: C ++ 14 อนุญาตเพียงแค่

    auto การประกาศอาร์กิวเมนต์ตัวระบุ( ... )

ตราบเท่าที่ฟังก์ชั่นถูกกำหนดไว้อย่างสมบูรณ์ก่อนการใช้งานและreturnคำสั่งทั้งหมดอนุมานเป็นประเภทเดียวกัน ->ไวยากรณ์ยังคงมีประโยชน์สำหรับฟังก์ชั่นของประชาชน (ประกาศในส่วนหัว) ถ้าคุณต้องการที่จะซ่อนร่างกายในแฟ้มแหล่งที่มา เห็นได้ชัดว่าไม่สามารถทำได้ด้วยเทมเพลต แต่มีบางประเภทที่เป็นรูปธรรม (โดยปกติจะได้มาจากการเขียนโปรแกรมแม่แบบ) ที่ยากที่จะเขียนเป็นอย่างอื่น


2
ดีมากเรียบร้อยและให้ข้อมูลตอบกลับ @Jan Hudec ยกนิ้วให้. เป็นสิ่งที่มีการเปลี่ยนแปลงในC++14ขณะที่ผมใช้autoสำหรับการreturnพิมพ์ในฟังก์ชั่นดังกล่าวโดยไม่จำเป็นต้องได้-> decltype(a + b)ส่วนหนึ่ง ตอนนี้มันซ้ำซ้อนหรือมีกรณีอื่นที่ควรใช้หรือไม่? หรือเป็นส่วนขยายเฉพาะของคอมไพเลอร์?
Shadi

1
@Shadi, C ++ 14 รวมถึงN3638ซึ่งอนุญาตให้หักประเภทการส่งคืนที่ประกาศเป็นautoโดยไม่มี->สัญกรณ์ตราบใดที่ฟังก์ชันถูกกำหนดอย่างสมบูรณ์ก่อนใช้งานและreturnคำสั่งทั้งหมดจะหักเป็นประเภทเดียวกัน ->สัญกรณ์ยังคงมีประโยชน์ถ้าคุณต้องการที่จะใช้ฟังก์ชั่นสำหรับการหักของประชาชนในขณะที่ซ่อนร่างกายในแฟ้มแหล่งที่มา
ม.ค. Hudec

24

ในภาษาอังกฤษธรรมดามันบอกว่าประเภทผลตอบแทนเป็นชนิดที่สรุปของผลรวมของและab

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.