จุดประสงค์ของ C ++ 20 std :: common_reference คืออะไร?


คำตอบ:


46

common_reference ออกมาจากความพยายามของฉันที่จะเกิดขึ้นกับแนวคิดของการทำซ้ำของ STL ที่รองรับพร็อกซี iterators

ใน STL ที่ iterators มีสองประเภทที่เกี่ยวข้องน่าสนใจโดยเฉพาะ: และreference value_typeอดีตคือชนิดส่งคืนของตัววนซ้ำoperator*และvalue_typeเป็นชนิด (ไม่ใช่ const, ไม่อ้างอิง) ขององค์ประกอบของลำดับ

อัลกอริทึมทั่วไปมักจะต้องทำสิ่งนี้:

value_type tmp = *it;

... เพื่อให้เรารู้ว่าต้องมีบางความสัมพันธ์ระหว่างทั้งสองประเภท สำหรับตัววนซ้ำที่ไม่ใช่พร็อกซีความสัมพันธ์นั้นง่าย: referenceเสมอvalue_typeตัวเลือกและการอ้างอิงที่ผ่านการรับรอง ความพยายามในการกำหนดInputIteratorแนวคิดเริ่มแรกนั้นจำเป็นต้องมีการแสดงออก*itซึ่งสามารถเปลี่ยนแปลงได้const value_type &และสำหรับตัววนซ้ำที่น่าสนใจที่สุดที่เพียงพอ

ฉันต้องการให้ผู้ทำซ้ำใน C ++ 20 มีประสิทธิภาพมากกว่านี้ ตัวอย่างเช่นพิจารณาความต้องการของzip_iteratorวนซ้ำสองลำดับในขั้นตอนการล็อก เมื่อคุณอ้างถึงzip_iteratorคุณจะได้รับประเภทpairการวนซ้ำสองreferenceแบบชั่วคราว ดังนั้นzip'ไอเอ็นจีvector<int>และ a vector<double>จะมีประเภทที่เกี่ยวข้องเหล่านี้:

zipiterator's reference: pair<int &, double &>
zipiterator's value_type:pair<int, double>

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

คำตอบใน C ++ 20 เป็นที่สำหรับใดประเภท iterator ถูกต้องหรือไม่พร็อกซี่ชนิดreference &&และvalue_type &แบ่งปันอ้างอิงทั่วไป กล่าวอีกนัยหนึ่งสำหรับตัววนซ้ำบางตัวitมีประเภทCRที่ทำให้เกิดรูปแบบต่อไปนี้:

void foo(CR) // CR is the common reference for iterator I
{}

void algo( I it, iter_value_t<I> val )
{
  foo(val); // OK, lvalue to value_type convertible to CR
  foo(*it); // OK, reference convertible to CR
}

CRเป็นการอ้างอิงทั่วไป อัลกอริทึมทั้งหมดสามารถพึ่งพาความจริงที่ว่ามีอยู่ประเภทนี้และสามารถใช้std::common_referenceในการคำนวณได้

นั่นคือบทบาทที่common_referenceเล่นใน STL ใน C ++ 20 โดยทั่วไปยกเว้นว่าคุณกำลังเขียนอัลกอริทึมทั่วไปหรือตัววนซ้ำพร็อกซีคุณสามารถละเว้นได้ อยู่ภายใต้การคุ้มครองเพื่อให้มั่นใจว่าตัววนซ้ำของคุณปฏิบัติตามภาระผูกพันตามสัญญา


แก้ไข: OP ยังขอตัวอย่าง นี้เป็นเพียงเล็กน้อย contrived แต่คิดว่ามันของ C ++ 20 และคุณจะได้รับช่วง random-access rประเภทRเกี่ยวกับการที่คุณจะรู้อะไรและคุณต้องการที่จะsortช่วง

คิดว่าต่อไปด้วยเหตุผลบางอย่างที่คุณต้องการที่จะใช้ฟังก์ชั่นการเปรียบเทียบ monomorphic std::less<T>เช่น (บางทีคุณอาจลบช่วงและคุณต้องลบฟังก์ชั่นการเปรียบเทียบแล้วพิมพ์มันผ่าน a virtualอีกครั้งยืด) สิ่งที่ควรTจะเป็นstd::less<T>? เพื่อที่คุณจะใช้common_referenceหรือผู้ช่วยiter_common_reference_tที่ถูกนำมาใช้ในแง่ของมัน

using CR = std::iter_common_reference_t<std::ranges::iterator_t<R>>;
std::ranges::sort(r, std::less<CR>{});

รับรองว่าใช้งานได้แม้ว่าช่วงrจะมีตัววนซ้ำพร็อกซี


2
บางทีฉันอาจจะหนาแน่น แต่คุณสามารถอธิบายให้ชัดเจนว่าการอ้างอิงทั่วไปในตัวอย่างเป็นอย่างไร
happydave

4
จะเป็นการดีpair<T&,U&>และจะมีการอ้างอิงทั่วไปและมันจะเป็นเพียงแค่pair<T,U>& pair<T&,U&>แต่สำหรับstd::pairที่มีการแปลงจากไม่มีpair<T,U>&การpair<T&,U&>แม้ว่าการแปลงดังกล่าวเป็นเสียงในหลักการ (สิ่งนี้โดยบังเอิญคือเหตุผลที่เราไม่มีzipมุมมองใน C ++ 20)
Eric Niebler

4
@EricNiebler: " นี่คือเหตุผลที่ว่าทำไมเราไม่มีมุมมอง zip ใน C ++ 20 " มีสาเหตุบางประการที่ต้องใช้ตัววนซ้ำของ zip ซ้ำpairแทนที่จะเป็นประเภทที่สามารถออกแบบมาเพื่อวัตถุประสงค์เฉพาะ ด้วยการแปลงที่เหมาะสมตามความจำเป็น?
Nicol Bolas

5
@Nicol Bolas ไม่จำเป็นต้องใช้std::pair; ประเภทคู่ที่เหมาะสมเช่นเดียวกับการแปลงที่เหมาะสมจะทำและ range-v3 กำหนดประเภทคู่เหมือน ในคณะกรรมการ LEWG ไม่ชอบความคิดที่จะเพิ่มประเภทของห้องสมุดมาตรฐานที่เกือบจะ แต่ไม่มากนักไม่std::pairว่าจะเป็นบรรทัดฐานหรือไม่โดยไม่ต้องขยันเนื่องจากข้อดีและข้อเสียของการstd::pairทำงาน
Eric Niebler

3
tuple, pair, tomato, -to - มีคุณลักษณะที่ดีที่คุณสามารถเข้าถึงองค์ประกอบด้วยและ การผูกที่มีโครงสร้างช่วยให้เกิดความอึดอัดใจในการทำงานกับs แต่ไม่ใช่ทั้งหมด MAHtopair.first.secondtuple
Eric Niebler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.