ฉันรู้ว่าคำถามนี้เก่า แต่มีวิธีแก้ปัญหานี้จนกระทั่งในที่สุด C ++ 20 ก็นำคุณสมบัตินี้จาก C เป็น C ++ สิ่งที่คุณสามารถทำได้เพื่อแก้ปัญหานี้คือใช้มาโครตัวประมวลผลล่วงหน้าที่มี static_asserts เพื่อตรวจสอบการเริ่มต้นของคุณว่าถูกต้อง (ฉันรู้ว่าโดยทั่วไปมาโครไม่ดี แต่ที่นี่ฉันไม่เห็นวิธีอื่น) ดูโค้ดตัวอย่างด้านล่าง:
#define INVALID_STRUCT_ERROR "Instantiation of struct failed: Type, order or number of attributes is wrong."
#define CREATE_STRUCT_1(type, identifier, m_1, p_1) \
{ p_1 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
#define CREATE_STRUCT_2(type, identifier, m_1, p_1, m_2, p_2) \
{ p_1, p_2 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
#define CREATE_STRUCT_4(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3, m_4, p_4) \
{ p_1, p_2, p_3, p_4 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_4) >= (offsetof(type, m_3) + sizeof(identifier.m_3)), INVALID_STRUCT_ERROR);\
จากนั้นเมื่อคุณมีโครงสร้างที่มีแอตทริบิวต์คุณสามารถทำได้:
struct MyStruct
{
const int attr1;
const float attr2;
const double attr3;
};
const MyStruct test = CREATE_STRUCT_3(MyStruct, test, attr1, 1, attr2, 2.f, attr3, 3.);
ไม่สะดวกเล็กน้อยเนื่องจากคุณต้องการมาโครสำหรับทุกแอตทริบิวต์ที่เป็นไปได้และคุณต้องทำซ้ำประเภทและชื่อของอินสแตนซ์ของคุณในการเรียกมาโคร นอกจากนี้คุณไม่สามารถใช้แมโครในคำสั่ง return เนื่องจากการยืนยันมาหลังจากการเริ่มต้น
แต่มันช่วยแก้ปัญหาของคุณได้: เมื่อคุณเปลี่ยนโครงสร้างการเรียกจะล้มเหลวในเวลาคอมไพล์
หากคุณใช้ C ++ 17 คุณสามารถทำให้มาโครเหล่านี้เข้มงวดขึ้นได้โดยบังคับให้ใช้ประเภทเดียวกันเช่น:
#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_1) == typeid(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_2) == typeid(identifier.m_2), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_3) == typeid(identifier.m_3), INVALID_STRUCT_ERROR);\