ของ AngewและjaggedSpire ของคำตอบที่ดีและนำไปใช้ค ++ 11. และc ++ 14. และค ++ 17.
อย่างไรก็ตามใน c ++ 20สิ่งต่างๆเปลี่ยนไปเล็กน้อยและตัวอย่างใน OP จะไม่รวบรวมอีกต่อไป:
class C {
C() = default;
};
C p;
auto q = C();
C r{};
auto s = C{};
ตามที่ระบุไว้ในคำตอบสองข้อเหตุผลที่การประกาศสองครั้งหลังใช้ได้ผลเพราะC
เป็นการรวมและนี่คือการเริ่มต้นรวม อย่างไรก็ตามจากผลของP1008 (โดยใช้ตัวอย่างที่จูงใจไม่ให้แตกต่างจาก OP มากเกินไป) คำจำกัดความของการเปลี่ยนแปลงโดยรวมใน C ++ 20 ถึงจาก[dcl.init.aggr] / 1 :
การรวมคืออาร์เรย์หรือคลาส ([คลาส]) ที่มี
- ไม่มีตัวสร้างที่ผู้ใช้ประกาศหรือสืบทอด ([class.ctor])
- ไม่มีสมาชิกข้อมูลโดยตรงที่เป็นส่วนตัวหรือได้รับการป้องกันโดยตรง ([class.access])
- ไม่มีฟังก์ชันเสมือน ([class.virtual]) และ
- ไม่มีคลาสพื้นฐานเสมือนส่วนตัวหรือที่มีการป้องกัน ([class.mi])
เน้นของฉัน ตอนนี้ความต้องการที่จะไม่ใช้การประกาศการก่อสร้างในขณะที่มันเคยเป็น (เป็นทั้งผู้ใช้อ้างอิงในคำตอบของพวกเขาและสามารถดูได้ในอดีตสำหรับC ++ 11 , C ++ 14และC ++ 17 ) ไม่มีผู้ใช้ให้ก่อสร้าง . ตัวสร้างเริ่มต้นสำหรับC
คือผู้ใช้ประกาศ แต่ไม่ได้ให้โดยผู้ใช้และด้วยเหตุนี้จึงสิ้นสุดการรวมใน C ++ 20
นี่คืออีกตัวอย่างที่แสดงให้เห็นถึงการเปลี่ยนแปลงโดยรวม:
class A { protected: A() { }; };
struct B : A { B() = default; };
auto x = B{};
B
ไม่ใช่การรวมใน C ++ 11 หรือ C ++ 14 เนื่องจากมีคลาสพื้นฐาน ด้วยเหตุนี้B{}
เพียงแค่เรียกใช้ตัวสร้างเริ่มต้น (ประกาศโดยผู้ใช้ แต่ไม่ได้ให้โดยผู้ใช้) ซึ่งสามารถเข้าถึงตัวA
สร้างเริ่มต้นที่ได้รับการป้องกัน
ใน C ++ 17 อันเป็นผลมาจากP0017 การรวมถูกขยายเพื่ออนุญาตให้มีคลาสพื้นฐาน B
คือการรวมใน C ++ 17 ซึ่งหมายความว่าB{}
เป็นการเริ่มต้นรวมที่ต้องเตรียมใช้งานวัตถุย่อยทั้งหมดรวมถึงA
วัตถุย่อย แต่เนื่องจากตัวA
สร้างเริ่มต้นได้รับการป้องกันเราจึงไม่สามารถเข้าถึงได้ดังนั้นการเริ่มต้นนี้จึงมีรูปแบบที่ไม่ถูกต้อง
ใน C ++ 20 เนื่องจากคอนB
สตรัคเตอร์ที่ผู้ใช้ประกาศไว้มันจึงยุติการรวมอีกครั้งดังนั้นจึงเปลี่ยนB{}
กลับเป็นการเรียกใช้คอนสตรัคเตอร์เริ่มต้นและนี่คือการเริ่มต้นที่มีรูปแบบที่ดีอีกครั้ง
C c{};
เริ่มต้นรวมจึงไม่มีการเรียกตัวสร้าง?