โครงสร้างข้อมูล STL ใดที่มีประเภทการจัดเก็บที่ไม่สมบูรณ์สามารถใช้เป็นสมาชิกของคลาสได้

เท่าที่ฉันรู้ เนื่องจาก C++17 โครงสร้างข้อมูล STL บางส่วนอาจมี "อยู่" โดยมีประเภทที่ไม่สมบูรณ์เป็นพารามิเตอร์เทมเพลตซึ่งอธิบายประเภทที่เก็บไว้ ตัวอย่างเช่น ฉันอาจใช้ std::unique_ptr<Incomplete> (ฉันไม่แน่ใจว่ามันเป็นโครงสร้างข้อมูลหรือไม่) หรือ std::vector<Incomplete> เป็นสมาชิกคลาส หากคุณสมบัติทั้งหมดของคลาส (ซึ่งต้องการคำจำกัดความของ Incomplete) ถูกนำไปใช้ในไฟล์ .cpp แยกต่างหาก:

class Incomplete;
using Complete = int;
class Foo {
private:
  std::unique_ptr<Incomplete> u_p;
  std::vector<Incomplete> v;
  std::deque<Incomplete> d;
  std::list<Incomplete> l;
  std::set<Incomplete> s;
  std::unordered_map<Complete, Complete> u_m_cc;
  std::unordered_map<Complete, Incomplete> u_m_ci;
  std::unordered_map<Incomplete, Complete> u_m_ic;
  std::unordered_map<Incomplete, Incomplete> u_m_ii;
public:
  // implemented in a separate .cpp which has Incomplete defined:
  Foo();
  Foo(Foo&&);
  Foo& operator=(Foo&&);
  Foo(Foo const&);
  Foo& operator=(Foo const&);
  ~Foo();
};

ดังนั้นสมาชิกข้อมูลใดที่ระบุไว้ข้างต้นที่ถูกต้องสำหรับการใช้งานดังกล่าว แล้วโครงสร้างข้อมูลอื่นๆ ตัวชี้อัจฉริยะ ฯลฯ ล่ะ?


person passing_through    schedule 01.02.2020    source แหล่งที่มา
comment
มันคอมไพล์หรือเปล่า? ถ้าไม่ สมาชิกคนไหนที่ทำให้เกิดข้อความวินิจฉัย?   -  person eerorika    schedule 01.02.2020
comment
@eerorika std::vector และ std::unique_ptr ไม่เป็นไร std::unordered_map ปฏิเสธที่จะทำงานกับ MSVC ของฉัน: std::pair ใช้ struct ที่ไม่สมบูรณ์ แม้ว่าจะมีการคอมไพล์บางอย่าง แต่ก็ไม่รับประกันว่าจะอยู่ในมาตรฐาน นั่นคือปัญหาที่ฉันเห็นในการทดสอบดังกล่าว   -  person passing_through    schedule 01.02.2020
comment
คอนเทนเนอร์ STL ที่จัดสรรบนฮีปจะทำงานกับประเภทที่ไม่สมบูรณ์ สิ่งที่จัดสรรบนสแต็กจะไม่และจะต้องมีส่วนหัวที่เหมาะสมรวมอยู่ด้วย std::pair คือ POD ดังนั้นคอนเทนเนอร์ใดๆ ที่มี std::pair เป็นสมาชิกจะไม่ทำงานกับประเภทที่ไม่สมบูรณ์ ข้อยกเว้นที่น่าสนใจอย่างหนึ่งคือ union โดยที่การจัดสรรอยู่บนสแต็ก แต่สมาชิกคนแรกของรายการสหภาพต้องเป็นประเภทที่สมบูรณ์ ส่วนอื่นๆ อาจไม่สมบูรณ์ก็ได้ ถ้าฉันจำได้ std::optional ใช้ประโยชน์จากคุณสมบัตินี้   -  person cplusplusrat    schedule 01.02.2020
comment
@cplusplusrat มีการระบุไว้ในมาตรฐาน C ++ 17 (หรือเก่า) หรือไม่ หมายความว่าฉันไม่สามารถใช้ std::unordered_map โดยจัดเก็บประเภทที่ไม่สมบูรณ์ได้หรือไม่ ถ้าเป็นเช่นนั้นมีทางเลือกอื่นหรือไม่?   -  person passing_through    schedule 01.02.2020
comment
@walnut: ประเภทเล็กน้อย (โดยอัตโนมัติ) จะเป็นเจ้าของทรัพยากรฮีปได้อย่างไร   -  person Davis Herring    schedule 02.02.2020
comment
@DavisHerring ฉันหมายถึง std::pair เอง ไม่ใช่สมาชิก เช่นเดียวกับประเภทอื่นๆ std::pair เองก็สามารถอยู่บนสแต็กหรือฮีปได้ ฉันพูดถึงเรื่องนั้นเพราะว่าสองสามประโยคแรกในความคิดเห็นที่ฉันตอบกลับไป มันฟังดูราวกับว่า std::pair การเป็นเรื่องเล็กน้อยทำให้ std::unordered_map ไม่สามารถยอมรับประเภทที่ไม่สมบูรณ์ได้ ซึ่งเท่าที่ฉันสามารถบอกได้ไม่ใช่ในกรณีนี้   -  person walnut    schedule 02.02.2020
comment
หากใครสนใจ: หากต้องการดำเนินการต่อด้วยการประกาศส่งต่อ ให้ใช้บูสต์คอนเทนเนอร์ที่มีการจัดสรรฮีป (และตัวจัดสรรที่เหมาะสมอย่างเห็นได้ชัด ค่าเริ่มต้นคือตกลง): ได้รับอนุญาตอย่างชัดเจน   -  person passing_through    schedule 03.02.2020


คำตอบ (2)


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

อาร์กิวเมนต์เทมเพลตอาจไม่สมบูรณ์ได้เสมอสำหรับ std::unique_ptr และ std::shared_ptr ตั้งแต่ C++11 โปรดดูที่ [unique.ptr]/5 และ [util.smartptr.shared]/2 ตามลำดับ

เพิ่มการรองรับประเภทที่ไม่สมบูรณ์ในคอนเทนเนอร์ด้วย N4510 ถึง C++17 แต่สำหรับเท่านั้น

std::vector
std::list
std::forward_list

และเฉพาะในกรณีที่ตัวจัดสรรที่ใช้เป็นไปตาม ข้อกำหนดความสมบูรณ์ของการจัดสรร กล่าวคือ แม้ว่าประเภทค่าจะไม่สมบูรณ์ ตัวจัดสรรประเภท X เองก็เป็นประเภทที่สมบูรณ์และเป็นสมาชิกทั้งหมดของ std::allocator_traits<X> เช่นกัน ยกเว้น ::value_type. ตัวจัดสรรเริ่มต้น std::allocator เป็นไปตามข้อกำหนดเหล่านี้

ไม่สามารถใช้คอนเทนเนอร์อื่นใดกับประเภทที่ไม่สมบูรณ์ได้ ตามข้อเสนอที่เชื่อมโยงด้านบน ขอบเขตถูกจำกัดอยู่ที่คอนเทนเนอร์ทั้งสามนี้ "เป็นขั้นตอนแรก" เนื่องจากการใช้งานหลักๆ ได้รับการรองรับแล้ว

person walnut    schedule 01.02.2020

เนื่องจาก C ++ 17 โครงสร้างข้อมูล STL บางส่วนอาจมี "อยู่" โดยมีประเภทที่ไม่สมบูรณ์เป็นพารามิเตอร์เทมเพลตซึ่งอธิบายประเภทที่เก็บไว้

สิ่งนี้ไม่ถูกต้อง

ตั้งแต่ C++17 เป็นต้นมา STL บางประเภทอาจถูกประกาศโดยมีประเภทที่ไม่สมบูรณ์เป็นพารามิเตอร์เทมเพลต

เมื่อถึงเวลาประเภท อินสแตนซ์ ประเภทจะต้องเสร็จสมบูรณ์

ตัวอย่างเช่น: (รหัสที่ยังไม่ได้ทดสอบ)

struct T; // incomplete
using TV = std::vector<T>; // declared a type using incomplete type T; fine.

TV tv0; // attempt to declare a variable of type TV; fails to compile.

struct T { int v; }; // T is now complete
TV tv1; // compiles
person Marshall Clow    schedule 01.02.2020
comment
ขอบคุณสำหรับการแก้ไข. ฉันยังไม่เข้าใจว่าประเพณีใดที่ฉันอธิบายไว้นั้นถูกต้อง ถ้ามี คุณช่วยในส่วนนี้ได้ไหม? - person passing_through; 01.02.2020
comment
ในตัวอย่างของ OP ไม่มีการสร้างอินสแตนซ์ของสมาชิกคอนเทนเนอร์ใด ๆ จนกว่าประเภทจะเสร็จสมบูรณ์ อนุญาตให้สร้างอินสแตนซ์ std::vector เอง (แต่ไม่ใช่สมาชิก) ด้วยประเภทที่ไม่สมบูรณ์ได้รับอนุญาตอย่างชัดเจนใน C ++ 17 ฉันไม่เห็นว่าคำอธิบายของคุณตอบคำถามอย่างไร - person walnut; 01.02.2020
comment
ประเภท list, forward_list และ vector ถูกเรียกอย่างชัดเจนใน C++17 - person Marshall Clow; 01.02.2020