“ การใช้ ODR” หมายความว่าอย่างไร


93

เพียงแค่นี้ก็ขึ้นมาในบริบทของคำถามอื่น

เห็นได้ชัดว่าฟังก์ชันสมาชิกในเทมเพลตคลาสจะถูกสร้างอินสแตนซ์เฉพาะเมื่อใช้ ODR ใครช่วยอธิบายได้ว่าหมายถึงอะไร บทความวิกิพีเดียหนึ่งนิยามกฎ (ODR)ไม่ได้พูดถึง " ODR การใช้งาน "

อย่างไรก็ตามมาตรฐานกำหนดให้เป็น

ตัวแปรที่มีชื่อปรากฏเป็นนิพจน์ที่มีการประเมินค่าจะถูกใช้แบบแปลกเว้นแต่ว่าจะเป็นอ็อบเจ็กต์ที่ตรงตามข้อกำหนดสำหรับการปรากฏในนิพจน์คงที่ (5.19) และการแปลงค่า lvalue-to-rvalue (4.1) จะถูกนำไปใช้ทันที

ใน [basic.def.odr]

แก้ไข: เห็นได้ชัดว่านี่เป็นส่วนที่ไม่ถูกต้องและทั้งย่อหน้ามีคำจำกัดความหลายคำสำหรับสิ่งต่างๆ นี่อาจเป็นสิ่งที่เกี่ยวข้องสำหรับฟังก์ชันสมาชิกเทมเพลตคลาส:

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

อย่างไรก็ตามฉันไม่เข้าใจว่ากฎนี้ทำงานอย่างไรกับหน่วยคอมไพล์หลาย ๆ หน่วย? ฟังก์ชันของสมาชิกทั้งหมดถูกสร้างอินสแตนซ์หรือไม่หากฉันสร้างอินสแตนซ์เทมเพลตคลาสอย่างชัดเจน


2
โปรดทราบว่า [basic.def.odr] / 6 ใช้กับฟังก์ชันสมาชิกของเทมเพลตคลาส "มีได้มากกว่าหนึ่งคำจำกัดความ [... ]"
dyp

3
"ฟังก์ชันของสมาชิกทั้งหมดถูกสร้างอินสแตนซ์หรือไม่หากฉันสร้างอินสแตนซ์เทมเพลตคลาสอย่างชัดเจน" ได้ดู [temp.explicit] / 8 + 9
dyp

คำตอบ:


72

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

คำจำกัดความเต็มอยู่ใน§3.2ย่อหน้าที่สองแม้ว่าจะมีการอ้างอิงถึงส่วนอื่น ๆ เพื่อให้คำจำกัดความสมบูรณ์

เกี่ยวกับเทมเพลต ODR ที่ใช้เป็นเพียงส่วนหนึ่งของคำถาม ส่วนอื่น ๆ คือการสร้างอินสแตนซ์ โดยเฉพาะอย่างยิ่ง§14.7จะครอบคลุมเมื่อเทมเพลตถูกสร้างอินสแตนซ์ แต่ทั้งสองมีความสัมพันธ์กัน: ในขณะที่ข้อความใน§14.7.1 (การสร้างอินสแตนซ์โดยนัย) มีความยาวพอสมควรหลักการพื้นฐานคือเทมเพลตจะถูกสร้างอินสแตนซ์ก็ต่อเมื่อมีการใช้และในบริบทนี้ใช้หมายถึงใช้ ODR ดังนั้นฟังก์ชันสมาชิกของเทมเพลตคลาสจะถูกสร้างอินสแตนซ์ก็ต่อเมื่อมีการเรียกใช้หรือถ้าเป็นแบบเสมือนและคลาสนั้นจะถูกสร้างอินสแตนซ์เอง มาตรฐานเองก็นับสิ่งนี้ในหลาย ๆ ที่นั่นคือการstd::list<>::sortใช้<กับแต่ละองค์ประกอบ แต่คุณสามารถสร้างอินสแตนซ์รายการผ่านประเภทองค์ประกอบที่ไม่รองรับได้<ตราบใดที่คุณไม่เรียกsortใช้


การใช้ ODR อาจทับซ้อนกับ "รูปธรรมชั่วคราว" ได้หรือไม่
v.oddou

23

ในคำธรรมดา odr-used หมายถึงบางสิ่ง (ตัวแปรหรือฟังก์ชัน) ถูกใช้ในบริบทที่ต้องมีการกำหนดนิยาม

เช่น,

struct F {
   static const int g_x = 2;
};

int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
                             // so it's OK without the definition of g_x

vector<int>  vi;
vi.push_back( F::g_x );      // Error, this is odr-used, push_back(const int & t) expect
                             // a const lvalue, so it's definition must be present

หมายเหตุ push_back ข้างต้นส่งผ่านใน MSVC 2013 ลักษณะการทำงานนี้ไม่ใช่การปฏิบัติตามมาตรฐานทั้ง gcc 4.8.2 และ clang 3.8.0 ล้มเหลวข้อความแสดงข้อผิดพลาดคือ: ไม่ได้กำหนดการอ้างอิงถึง `` K :: g_x '


เป็นไปได้ไหมที่จะใช้สมาชิกข้อมูลแบบคงที่เหมือนvi.push_back( F::g_x );ใน c ++?
Rankaba

แต่ยังสามารถส่งผ่านค่า rvalue ไปได้const int&หรือไม่สมาชิก const คงที่สามารถถูกลบล้างเป็น rvalue ได้หรือไม่
scottxiao

8
+1 สำหรับประโยคเปิดที่รวบรัด: "ในคำธรรมดา odr-used หมายถึงบางสิ่ง (ตัวแปรหรือฟังก์ชัน) ถูกใช้ในบริบทที่ต้องมีการกำหนดคำจำกัดความ"
Paul Masri-Stone

1
ฉันไม่เข้าใจว่าคุณรวบรวมโค้ดนั้นอย่างไร อยู่ม ธ . เดียวกันหรือเปล่า?. ถ้าเป็นเช่นนั้น F :: g_x ได้กำหนดไว้ก่อนpush_backแล้วแน่นอนว่ามันจะผ่านไป ไม่ใช่เหรอ?
Lewis Chan

1
@bigxiao " สามารถส่งค่า rvalue ได้ " ใช่และวัตถุชั่วคราวถูกสร้างขึ้นโดยคอมไพลเลอร์และการอ้างอิงที่ผูกไว้กับวัตถุนั้น OTOH เมื่อผ่าน lvalue ซึ่งหมายถึงการส่งผ่านวัตถุนั้นที่อ้างถึงโดยการประเมินค่า lvalue: เมื่อคุณส่ง lvalue คุณสามารถคาดหวังว่าพารามิเตอร์ในฟังก์ชันจะอ้างถึงวัตถุที่ถูกต้อง คอมไพเลอร์จะไม่สร้างไฟล์. หากคุณต้องการชั่วคราวให้สร้างด้วยoperator+.
ซอกแซก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.