C ++ 20 std::common_reference
แนะนำ จุดประสงค์ของมันคืออะไร? ใครสามารถยกตัวอย่างการใช้งานได้บ้าง
C ++ 20 std::common_reference
แนะนำ จุดประสงค์ของมันคืออะไร? ใครสามารถยกตัวอย่างการใช้งานได้บ้าง
คำตอบ:
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>
จะมีประเภทที่เกี่ยวข้องเหล่านี้:
zip
iterator's reference
: pair<int &, double &>
zip
iterator'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
จะมีตัววนซ้ำพร็อกซี
pair<T&,U&>
และจะมีการอ้างอิงทั่วไปและมันจะเป็นเพียงแค่pair<T,U>&
pair<T&,U&>
แต่สำหรับstd::pair
ที่มีการแปลงจากไม่มีpair<T,U>&
การpair<T&,U&>
แม้ว่าการแปลงดังกล่าวเป็นเสียงในหลักการ (สิ่งนี้โดยบังเอิญคือเหตุผลที่เราไม่มีzip
มุมมองใน C ++ 20)
pair
แทนที่จะเป็นประเภทที่สามารถออกแบบมาเพื่อวัตถุประสงค์เฉพาะ ด้วยการแปลงที่เหมาะสมตามความจำเป็น?
std::pair
; ประเภทคู่ที่เหมาะสมเช่นเดียวกับการแปลงที่เหมาะสมจะทำและ range-v3 กำหนดประเภทคู่เหมือน ในคณะกรรมการ LEWG ไม่ชอบความคิดที่จะเพิ่มประเภทของห้องสมุดมาตรฐานที่เกือบจะ แต่ไม่มากนักไม่std::pair
ว่าจะเป็นบรรทัดฐานหรือไม่โดยไม่ต้องขยันเนื่องจากข้อดีและข้อเสียของการstd::pair
ทำงาน
tuple
, pair
, tomato
, -to
- มีคุณลักษณะที่ดีที่คุณสามารถเข้าถึงองค์ประกอบด้วยและ การผูกที่มีโครงสร้างช่วยให้เกิดความอึดอัดใจในการทำงานกับs แต่ไม่ใช่ทั้งหมด MAH
to
pair
.first
.second
tuple