类型和initializer_list不完整
Incomplete types and initializer_list
我正在尝试对一些元数据进行建模,以便序列化/反序列化C++对象。这里有一些捕捉坚果的东西&我需要的螺栓;它与GCC 5.2(g++ sample.cpp -std=c++14
)和Clang 3.6(clang++ sample.cpp -std=c++14
)进行编译。
我的问题是关于示例中的struct TypeInfo
。它本身包含一个std::initializer_list
。这个标准符合吗?
#include <cstdint>
#include <initializer_list>
enum class TypeCode : std::uint8_t { BOOLEAN, INT, OBJECT, STRING, SENTINEL };
struct TypeInfo
{
TypeCode typeCode_;
char fieldName_[64];
union
{
std::uint16_t textMinLength_;
std::uint16_t objectVersionMajor_;
};
union
{
std::uint16_t textMaxLength_;
std::uint16_t objectVersionMinor_;
};
// set only if typeCode_ = OBJECT
std::initializer_list < TypeInfo > objectTypeInfos_;
};
int main()
{
TypeInfo const sti { TypeCode::STRING, "updatedBy", { .textMinLength_ = 0 }, { .textMaxLength_ = 16 } };
TypeInfo const iti { TypeCode::INT, "amount", { 0 }, { 0 } };
TypeInfo const oti { TypeCode::OBJECT, "startTime", { .objectVersionMajor_ = 1 }, { .objectVersionMinor_ = 0 }, {
TypeInfo { TypeCode::INT, "weekdays", { 0 }, { 0 } },
TypeInfo { TypeCode::INT, "timeOfDay", { 0 }, { 0 } },
TypeInfo { TypeCode::STRING, "timezone", { .textMinLength_ = 0 }, { .textMaxLength_ = 5 } }
} };
TypeInfo const noti { TypeCode::OBJECT, "schedule", { .objectVersionMajor_ = 1 }, { .objectVersionMinor_ = 0 }, {
TypeInfo { TypeCode::INT, "id", { 0 }, { 0 } },
TypeInfo { TypeCode::STRING, "description", { .textMinLength_ = 0 }, { .textMaxLength_ = 16 } },
TypeInfo { TypeCode::OBJECT, "startTime", { .objectVersionMajor_ = 1 }, { .objectVersionMinor_ = 0 }, {
TypeInfo { TypeCode::INT, "weekdays", { 0 }, { 0 } },
TypeInfo { TypeCode::INT, "timeOfDay", { 0 }, { 0 } },
TypeInfo { TypeCode::STRING, "timezone", { .textMinLength_ = 0 }, { .textMaxLength_ = 5 } }
} }
} };
}
这实际上导致了当前措辞的未定义行为。在实例化std::initializer_list<TypeInfo>
时,TypeInfo
是不完整的,因此[res.on.functions]/(2.5)适用:
特别是,在以下情况下,影响是未定义的:
(2.5)--如果使用不完整类型(3.9)作为模板参数实例化模板组件,除非特别允许该组件。
…并且initializer_list
还不允许使用不完全类型——然而,这显然是有缺陷的。LWG问题2493选择修复此问题:
std::initializer_list<T>
的典型用例用于传递T
的构造函数的值参数。然而,这违反了[res.on.functions]/2.5,因为initializer_list没有具体说明允许不完整的类型(例如std::unique_ptr
([unique.ptr]/5)和std::enable_shared_from_this
([util.smartptr.enab]/2)).一个解决方案是从这样的段落
也就是说,您的代码是好的(并且在解决上述DR后将正式好起来)。
§[res.on.functions]/2:
特别是,在以下情况下,效果是未定义的:
[…]
(2.5)-如果在实例化模板组件时使用不完整类型(3.9)作为模板参数,除非该组件特别允许。
我认为initializer_list
在不完整类型上实例化没有这样的具体允许(至少在N4296之前,在§[dcl.init.list]或§[support.init.list中)。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- C++中带有List类的迭代器Segfault
- 使用"std::unordereded_map"映射到"std::list"对象
- GCC对可能有效的代码抛出init list生存期警告
- 使用std::list创建循环链表
- C2664 无法从'initializer list'转换参数
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错
- 在C++中标记化"Braced Initializer List"样式字符串(使用 Boost?
- "默认参数":无法从'initializer list'转换为'std::initializer_list'
- 无法从'initializer-list'转换为用户控制器
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- 递归调用中出现错误"[Error] expression list treated as compound expression in initializer [-fpermissive]"
- VS2015无法从'initializer list'转换为'std::string'错误
- 编译器错误:"Non-aggregates cannot be initialized with initializer list."
- 无法转换...从 '<brace-enclosed initializer list>' 到 地图
- 无法将'<brace-enclosed initializer list>'转换为'double'作为回报
- <function-style-cast> 错误:无法从'initializer list'转换为'std::thread'
- initializer语言 - list不能转换为const margin *