ทำไม Remove_reference ไม่ทำงานกับฟังก์ชั่น?


38

วิ่งเข้าไปหาสิ่งที่แปลกประหลาดเมื่อทำเทมเพลต metaprogramming บางวัน โดยพื้นฐานแล้วมาจากการยืนยันนี้ไม่ผ่าน (อย่างที่ฉันคาดหวัง)

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

ตอนแรกฉันคิดว่าฉันทำผิดพลาดทางไวยากรณ์ที่กำหนดฟังก์ชันอ้างอิง แต่การยืนยันนี้ผ่านไปโดยแสดงว่าไม่เป็นเช่นนั้น

static_assert(std::is_same_v<void()&, void()&>);

ฉันยังลองใช้remove_referenceตัวเองเพื่อคัดลอกแหล่งที่มาจาก cppreference แต่ก็ไม่ได้ผลเช่นกัน เกิดขึ้นที่นี่คืออะไร?

คำตอบ:


42

ยินดีต้อนรับสู่โลกแห่งประเภทฟังก์ชั่นที่น่ารังเกียจ

void() &คือไม่ได้void()มีการอ้างอิงถึง วิธีการสะกดที่จะvoid(&)()(ซึ่งถ้าคุณremove_reference_tคุณจะได้รับกลับมาvoid()- นั่นคือremove_reference_t ไม่ทำงานในการอ้างอิงถึงฟังก์ชั่นถ้าสิ่งที่คุณให้มันเป็นจริงมีการอ้างอิงถึงประเภทฟังก์ชั่น)

สิ่งที่void() &อ้างถึงจริง ๆ คือประเภทของฟังก์ชันสมาชิกที่มีคุณสมบัติอ้างอิงหลังจากที่คุณตัดคลาสออก นั่นคือ:

struct C {
    void f() &;
};

ประเภทของการมี&C::f void (C::*)() &แต่ชี้ทั้งหมดให้กับสมาชิกสามารถเขียนเป็นT C::*สำหรับบางชนิดTและในกรณีนี้ชนิดจะเป็นTvoid() &

ดูเพิ่มเติมP0172


3
ใครบางคนควรสร้างคำถามที่ยอมรับได้สำหรับประเภทฟังก์ชั่นที่น่ารังเกียจ
Brian

ว้าว C ++ ไม่เคยล้มเหลวที่จะทำให้ฉันประหลาดใจแม้ว่าฉันจะเรียนรู้และใช้มันมาเกือบ 10 ปีแล้วก็ตาม
เคลวินหู

13

ชนิดที่คุณมีไม่ได้มีการอ้างอิงถึงฟังก์ชั่น แต่ฟังก์ชั่นที่มีรอบคัดเลือกอ้างอิง

static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.