l-values ​​ส่งผ่านไปยัง std :: make_pair ได้อย่างไร

Aug 16 2020

ในstd::make_pair มีเพียงหนึ่งการดำเนินงาน C ++ 14 เป็นต้นไป

เทมเพลต <class T1, class T2> constexpr std :: pair <V1, V2> make_pair (T1 && t, T2 && u);

พารามิเตอร์ทั้งสองคือการอ้างอิงค่า R และตามนี้

การอ้างอิงค่า R ไม่สามารถเริ่มต้นด้วยค่า l

    int i = 1;
    char ch = 'a';
    std::unordered_map<int, char> mp;
    mp.insert(make_pair<int,char>(i, ch));

ดังนั้นเมื่อผมพยายามที่จะใช้ make_pair error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'ในรหัสดังกล่าวข้างต้นได้อย่างถูกต้องโยนข้อผิดพลาด

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

mp.insert(make_pair(i, ch));

ฉันสับสนว่ามันทำงานอย่างไรiและchทั้งสองเป็นค่า L ความละเอียดของอาร์กิวเมนต์แม่แบบแปลงค่า L เป็นค่า R หรือไม่หรือชอบวิธีการนี้

คำตอบ

3 songyuanyao Aug 16 2020 at 08:06

พารามิเตอร์ของmake_pairยังไม่ได้ประกาศเป็น rvalue อ้างอิง แต่อ้างอิงส่งต่อ

การอ้างอิงการส่งต่อเป็นการอ้างอิงชนิดพิเศษที่เก็บรักษาหมวดหมู่ค่าของอาร์กิวเมนต์ของฟังก์ชันทำให้สามารถส่งต่อได้โดยใช้ std :: forward การอ้างอิงการส่งต่อ ได้แก่ :

  1. พารามิเตอร์ฟังก์ชันของเทมเพลตฟังก์ชันที่ประกาศเป็นการอ้างอิง rvalue ไปยังพารามิเตอร์เทมเพลตชนิด cv-unqualified ของเทมเพลตฟังก์ชันเดียวกันนั้น:

การส่งผลงาน referece กับทั้ง lvalues และ rvalues ด้วยความช่วยเหลือของแม่แบบหักข้อโต้แย้ง เมื่อส่งผ่าน lvalue พารามิเตอร์ template จะถูกอนุมานเป็น lvalue-reference หลังจากการยุบการอ้างอิงพารามิเตอร์ของฟังก์ชันคือ lvalue-reference ด้วย เมื่อส่งผ่าน rvalue พารามิเตอร์ template จะถูกอนุมานว่าไม่อ้างอิงพารามิเตอร์ของฟังก์ชันคือ rvalue-reference

ในทางกลับกันถ้าคุณระบุอาร์กิวเมนต์แม่แบบอย่างชัดเจนmake_pair<int,char>(...)พารามิเตอร์ฟังก์ชันจะกลายเป็น rvalue-reference ตาม

1 JaMiT Aug 16 2020 at 11:01

คำตอบโดย songyuanyaoแล้วอธิบายว่าส่วนใหญ่ของสิ่งที่เกิดขึ้น แม้ว่าฉันอยากจะมีส่วนร่วมในการทำให้สิ่งนี้ทำงานได้โดยใช้อาร์กิวเมนต์เทมเพลตที่ชัดเจน คุณอยู่ที่นั่นเกือบทั้งหมด แต่ไม่ได้ทำตามขั้นตอนสุดท้าย

ฉันสับสนว่ามันทำงานอย่างไรiและchทั้งสองเป็นค่า L

ตรง คุณต้องการค่า l ซึ่งเป็นสิ่งที่คุณสามารถระบุได้ในอาร์กิวเมนต์ของเทมเพลต:

std::make_pair<int &, char &>(i, ch)

หรือรูปแบบที่ใช้ได้ในหลายกรณี:

std::make_pair<const int &, const char &>(i, ch)

การเขียนเพิ่มเติมเล็กน้อย แต่จำเป็นหากการหักอาร์กิวเมนต์ล้มเหลวด้วยเหตุผลบางประการ