Я знаю, що це питання давнє, але є спосіб вирішити це питання, поки 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);\
// Create more macros for structs with more attributes...
Тоді, коли у вас є структура з атрибутами const, ви можете це зробити:
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.);
Це трохи незручно, тому що вам потрібні макроси для кожної можливої кількості атрибутів, і вам потрібно повторити тип і ім'я свого примірника у виклику макросу. Також ви не можете використовувати макрос у зворотному операторі, тому що твердження з’являються після ініціалізації.
Але це все-таки вирішує вашу проблему: Коли ви зміните структуру, виклик буде невдалим під час компіляції.
Якщо ви використовуєте 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);\