ปรับปรุง:ใน C ++ 11 หนึ่งอาจจะใช้แทนstd::addressof
boost::addressof
ให้เราคัดลอกรหัสจาก Boost ก่อนลบคอมไพเลอร์ทำงานกับบิต:
template<class T>
struct addr_impl_ref
{
T & v_;
inline addr_impl_ref( T & v ): v_( v ) {}
inline operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
};
template<class T>
struct addressof_impl
{
static inline T * f( T & v, long ) {
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
static inline T * f( T * v, int ) { return v; }
};
template<class T>
T * addressof( T & v ) {
return addressof_impl<T>::f( addr_impl_ref<T>( v ), 0 );
}
จะเกิดอะไรขึ้นถ้าเราผ่านการอ้างอิงถึงฟังก์ชั่น ?
หมายเหตุ: addressof
ไม่สามารถใช้กับตัวชี้ไปยังฟังก์ชั่น
ใน C ++ หากvoid func();
มีการประกาศไว้func
จะมีการอ้างอิงไปยังฟังก์ชันที่ไม่มีการโต้แย้งและไม่มีผลลัพธ์ การอ้างอิงถึงฟังก์ชั่นนี้สามารถแปลงเป็นตัวชี้ไปยังฟังก์ชั่นได้เล็กน้อยจาก - @Konstantin
ตาม: 13.3.3.2 ทั้งคู่T &
และT *
แยกไม่ออกสำหรับฟังก์ชัน ฟังก์ชั่นที่หนึ่งคือการแปลงข้อมูลประจำตัวและที่สองคือการแปลงฟังก์ชันเป็นตัวชี้ทั้งสองมีอันดับ "การจับคู่แบบตรงทั้งหมด" (13.3.3.1.1 ตารางที่ 9)
การอ้างอิงฟังก์ชันผ่านaddr_impl_ref
มีความคลุมเครือในการแก้ปัญหาโอเวอร์โหลดสำหรับตัวเลือกf
ซึ่งแก้ไขได้ด้วยอาร์กิวเมนต์ดัมมี่0
ซึ่งเป็นint
ครั้งแรกและสามารถเลื่อนเป็นlong
(การแปลงอินทิกรัล)
ดังนั้นเราเพียงแค่ส่งกลับตัวชี้
จะเกิดอะไรขึ้นถ้าเราส่งประเภทด้วยตัวดำเนินการแปลง
หากผู้ประกอบการแปลงให้ผลตอบแทนT*
แล้วเรามีความกำกวม: สำหรับf(T&,long)
การส่งเสริมการขายเป็นสิ่งจำเป็นสำหรับการโต้แย้งที่สองในขณะที่สำหรับf(T*,int)
ผู้ประกอบการแปลงจะถูกเรียกในครั้งแรก(ขอบคุณ @litb)
นั่นคือเมื่อaddr_impl_ref
เริ่มใช้งานมาตรฐาน C ++ กำหนดว่าลำดับการแปลงอาจมีการแปลงที่ผู้ใช้กำหนดสูงสุดหนึ่งรายการ ด้วยการห่อประเภทaddr_impl_ref
และบังคับให้ใช้ลำดับการแปลงแล้วเราจะ "ปิด" ผู้ให้บริการการแปลงที่มาพร้อมกับประเภทนั้น
ดังนั้นจึงf(T&,long)
มีการเลือกเกินพิกัด (และดำเนินการโปรโมตอินทิกรัล)
จะเกิดอะไรขึ้นกับคนอื่น ๆ ?
ดังนั้นการf(T&,long)
เลือกเกินพิกัดเนื่องจากมีประเภทไม่ตรงกับT*
พารามิเตอร์
หมายเหตุ: จากข้อสังเกตในไฟล์ที่เกี่ยวกับความเข้ากันได้ของ Borland อาร์เรย์จะไม่สลายตัวไปยังพอยน์เตอร์ แต่ถูกส่งผ่านโดยการอ้างอิง
เกิดอะไรขึ้นกับการโอเวอร์โหลดนี้
เราต้องการหลีกเลี่ยงการใช้operator&
กับประเภทเนื่องจากอาจมีการใช้งานมากเกินไป
การรับรองมาตรฐานที่reinterpret_cast
อาจใช้กับงานนี้ (ดูคำตอบของ @Matteo Italia: 5.2.10 / 10)
Boost เพิ่มสิ่งที่น่าสนใจด้วยconst
และตัวระบุvolatile
เพื่อหลีกเลี่ยงคำเตือนของคอมไพเลอร์ (และใช้ a const_cast
เพื่อลบออกอย่างเหมาะสม)
- ส่ง
T&
ไปที่char const volatile&
- เปลื้องผ้า
const
และvolatile
- ใช้
&
โอเปอเรเตอร์เพื่อจดที่อยู่
- โยนกลับไปที่
T*
กระบวนการconst
/ volatile
การเล่นกลเป็นบิตของมนต์ดำ แต่มันทำให้งานง่ายขึ้น (แทนที่จะให้การโอเวอร์โหลดเกิน 4 ครั้ง) หมายเหตุว่าตั้งแต่T
เป็นอย่างไม่มีเงื่อนไขถ้าเราผ่านghost const&
แล้วT*
เป็นghost const*
จึงบ่นยังไม่ได้รับมันหายไป
แก้ไข:ตัวชี้โอเวอร์โหลดใช้สำหรับตัวชี้ไปยังฟังก์ชั่นฉันแก้ไขคำอธิบายข้างต้นบ้าง ผมก็ยังไม่เข้าใจว่าทำไมมันเป็นสิ่งที่จำเป็นแม้ว่า
เอาท์พุท ideoneต่อไปนี้สรุปสิ่งนี้ขึ้นมาบ้าง