不完整的类型和initializer_list

zrb*_*zrb 8 c++ c++14

我正在尝试为序列化/反序列化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 } }
      } }
    } };
}
Run Code Online (Sandbox Code Playgroud)

Col*_*mbo 3

这实际上会导致当前措辞中未定义的行为。在 的实例化点std::initializer_list<TypeInfo>TypeInfo是不完整的,因此 [res.on.functions]/(2.5) 适用:

\n\n
\n

特别是,在以下情况下效果未定义:
(2.5)\n \xe2\x80\x94 如果在实例化模板组件时使用不完整类型 (3.9) 作为模板参数,\n 除非特别允许\n该组件。

\n
\n\n

\xe2\x80\xa6 和不完整类型尚未明确允许initializer_list- 然而,这显然是有缺陷的。LWG问题 2493选择修复此问题:

\n\n
\n

的典型用例std::initializer_list<T>是\n 构造函数的按值传递参数T。然而,这违反了\n [res.on.functions]/2.5,因为initializer_list 并没有明确\n 允许不完整的类型(例如std::unique_ptr\n ([unique.ptr]/5) 和std::enable_shared_from_this\n ([util.ptr])。 smartptr.enab]/2))。

\n\n

解决方案是从此类段落中复制粘贴相关文本。\n

\n
\n\n

也就是说,您的代码很好(并且在解决上述 DR 后将正式正常)。

\n

  • ...至少假设灾难恢复已按照您的预期得到解决。自提交以来尚未采取任何行动,因此仍可将其解析为“NAD”。我怀疑这种情况会发生,但仍然不能保证它会得到解决以支持不完整的类型。 (2认同)