เหตุใดจึงต้องมีการกำหนดค่าเริ่มต้นในวงเล็บเหลี่ยมแบบมาตรฐานสำหรับ `make_‹something›`

ฟังก์ชัน std::make_ ในมาตรฐาน เช่น:

  • std::make_unique และ std::make_shared
  • std::make_tuple
  • std::make_from_tuple

ทั้งหมดใช้ การเริ่มต้นวงเล็บกลม ภายใน แทนที่จะเป็น วงเล็บปีกกา

ตัวอย่างเช่น make_from_tuple ตามที่มาตรฐานนำเสนอ เลือกที่จะส่งคืน T(params...) แทน กว่า T{params...}

ผลลัพธ์ก็คือสิ่งต่อไปนี้ผิดกฎหมาย:

auto vec = std::make_from_tuple<std::vector<int>>(std::make_tuple());
auto arr = std::make_from_tuple<std::array<int, 2>>(std::make_tuple(9, 8));

^การสร้าง std::array จาก tuple ดังที่กล่าวข้างต้นคือ ผิดกฎหมายด้วย C++20 เช่น p0960 - อนุญาตให้เริ่มต้นการรวมจากรายการค่าในวงเล็บกลายเป็น เป็นส่วนหนึ่งของ ข้อมูลจำเพาะของ C++20 ไม่อนุญาตให้มีการกำหนดค่าเริ่มต้นดังกล่าวสำหรับ std::array เนื่องจากประเภทภายในคือ T[size] ซึ่งไม่สามารถเตรียมใช้งานจากรายการค่าได้ (วงเล็บถูกลบออกด้วยการเริ่มต้น std::array แล้ว)


ในกรณีที่ใช้งานได้ การเลือกการเริ่มต้นวงเล็บเหลี่ยมเทียบกับวงเล็บปีกกาจะมีความหมาย:

auto vec2 = std::make_from_tuple<std::vector<int>>(std::make_tuple(2, 3));
// a vector with the values: {3, 3} surprise? :-)

(แน่นอนว่าข้างต้นคือ ตัวอย่างของเล่น ทูเพิลที่ให้มาอาจถูกจัดเตรียมไว้ภายนอก)

ด้วยการชอบ curly_make_from_tuple:

template<typename T, typename tuple_t>
constexpr auto curly_make_from_tuple(tuple_t&& tuple) {
    constexpr auto get_T = [](auto&& ... x){ return T{std::forward<decltype(x)>(x) ... }; };
    return std::apply(get_T, std::forward<tuple_t>(tuple));
}

ทุกกรณีข้างต้นจะใช้ได้ผล ในลักษณะที่อาจโต้แย้งได้ว่าเป็นธรรมชาติมากกว่า:

auto arr = curly_make_from_tuple<std::array<int, 2>>(std::make_tuple(9, 8)); // {9, 8}
auto vec = curly_make_from_tuple<std::vector<int>>(std::make_tuple());       // {}
auto vec2 = curly_make_from_tuple<std::vector<int>>(std::make_tuple(2, 3));  // {2, 3}

คำถามคือ: เหตุใดมาตรฐานจึงเลือก การเริ่มต้นวงเล็บกลม มากกว่า วงเล็บปีกกา?


ลิงก์ที่เกี่ยวข้อง:

คำถามที่คล้ายกันจากมุมมองด้านประสิทธิภาพ: ทำไม การใช้งาน make_tuple ไม่ส่งคืนผ่านการเริ่มต้นวงเล็บปีกกาใช่ไหม

การสนทนาและคำแนะนำที่ดีสำหรับการเพิ่มการเริ่มต้นวงเล็บปีกกา ตัวเลือกสำหรับ `ยูทิลิตี้ make_`

บทความต้นฉบับเสนอ make_from_tuple, P0209r2 ดูเหมือนจะไม่พูดถึงสองทางเลือก T(params...) และ T{params...} อาจเป็นเพราะวิธีอรรถประโยชน์ make_ ที่คล้ายกันทั้งหมดได้ใช้การเริ่มต้นวงเล็บเหลี่ยมแล้ว


person Amir Kirsh    schedule 26.05.2020    source แหล่งที่มา
comment
การเรียกใช้ฟังก์ชันจะใช้วงเล็บเหลี่ยมเสมอ นั่นคือไวยากรณ์ของภาษา วงเล็บปีกกาใช้สำหรับรายการตัวเริ่มต้น   -  person sanitizedUser    schedule 26.05.2020
comment
คุณถามว่าทำไมพวกเขาถึงใช้ T(std::forward<decltype(x)>(x) ... ) แทน T{std::forward<decltype(x)>(x) ... }?   -  person NathanOliver    schedule 26.05.2020
comment
@NathanOliver ใช่ โดยไม่สนใจตัวเลือกแฟนซีที่จะสนับสนุนทั้งสอง (ดังที่กล่าวไว้ในลิงค์ที่ 2 ที่ให้ไว้ตอนท้าย) หากควรได้รับการสนับสนุน ทำไมต้องใช้วงเล็บกลม?   -  person Amir Kirsh    schedule 26.05.2020
comment
มันไม่ใช่การเริ่มต้น แต่เป็นการเรียกใช้ฟังก์ชัน std::make_unique, std::make_shared, std::make_tuple ฯลฯ ไม่ได้เตรียมใช้งานสิ่งต่าง ๆ แต่จะส่งคืนอ็อบเจ็กต์และข้อดีของพวกมันคือความปลอดภัยของเธรด ความเรียบง่าย ฯลฯ   -  person asmmo    schedule 26.05.2020
comment
@asmmo คำถามอยู่ที่การใช้งานฟังก์ชันเหล่านี้ ภายใน   -  person Amir Kirsh    schedule 26.05.2020
comment
คำถามที่เกี่ยวข้องอีกข้อพร้อมคำตอบที่น่าสนใจมากมายสามารถพบได้ที่นี่: stackoverflow.com/questions/55141594/   -  person Yehezkel B.    schedule 26.05.2020


คำตอบ (1)


เนื่องจากไม่สามารถเตรียมใช้งานโครงสร้างโดยใช้ brad-init-list ใน C++98 ได้

ดังนั้นเพื่อความสอดคล้อง คุณลักษณะไลบรารีมาตรฐานใหม่จึงใช้แบบฟอร์มการเริ่มต้นเดียวกันกับที่ใช้ใน STL

ยิ่งไปกว่านั้น ไม่เคยถูกเปลี่ยนเป็นการเริ่มต้นรายการด้วยเหตุผลด้านความเข้ากันได้: การเริ่มต้นรายการไม่จำเป็นต้องมีความหมายเหมือนกับแบบฟอร์มการเริ่มต้นในวงเล็บที่เทียบเท่ากัน

person Oliv    schedule 26.05.2020
comment
ฟังก์ชันไลบรารีใดก่อน C ++ 11 ที่สร้างวัตถุเช่นนั้น อาจไม่มีเลย เนื่องจากต้องใช้เทมเพลตที่หลากหลาย ดังนั้นหากฟังก์ชันดังกล่าวทั้งหมดปรากฏใน C++11 หรือหลังจากนั้น ก็อาจใช้การกำหนดค่าเริ่มต้นด้วยปีกกาได้ แน่นอนว่าจะต้องเลือกใครคนหนึ่งหากไม่ใช้แนวทางแฟนซีในการสนับสนุนทั้งสองอย่าง แต่คณะกรรมการได้พิจารณาทั้งสองอย่างหรือไม่? เป็น การตัดสินใจโดยเจตนา หรือไม่? - person Amir Kirsh; 27.05.2020
comment
@AmirKirsh สำหรับตัวอย่างตัวจัดสรร STL สำหรับการสร้างสำเนา - person Oliv; 27.05.2020