【问题标题】:Initialisation of aggregate with default constructor deleted in c++20在 c++20 中使用删除的默认构造函数初始化聚合
【发布时间】:2019-11-30 21:14:37
【问题描述】:

删除了包含 POD 和默认构造函数的结构。当使用-std=c++2a 编译时,尝试聚合初始化结构的实例会导致 g++9.1 中的编译错误。使用-std=c++17 可以正常编译相同的代码。

https://godbolt.org/z/xlRHLL

struct S
{
    int a;
    S() = delete;
};

int main()
{
    S s {.a = 0};
}

【问题讨论】:

    标签: c++ c++17 c++20 aggregate-initialization deleted-functions


    【解决方案1】:

    您的 struct 不是 C++20 以来的聚合。

    聚合的定义再次改变:

    cppreference

    聚合是以下类型之一:

    • ...

    • 类类型(通常为structunion),具有

      • ...

      • 没有用户提供的、继承的或显式的构造函数(允许显式默认或删除的构造函数)
        (C++17 起)(C++20 前)

      • 没有用户声明或继承的构造函数
        (C++20 起)

    IMO,这修复了语言中的一个缺陷。能够使用已删除或无法访问的构造函数构造(通过聚合初始化)对象对我来说并不合适。

    【讨论】:

    • 这是执行此操作的提案,其中包括基本原理:open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1008r1.pdf
    • 当然,聚合初始化不应允许意外绕过已删除的构造函数。但这不是 c++20 所做的更改。它做了更广泛的事情。删除的 ctor 也将取消聚合。但是好吧,我明白为什么了。例如如果您的副本 ctor 被删除,那么您不会意外地通过聚合初始化创建副本,但您仍然可以有目的地这样做,而且您似乎也不希望这样做。好的,但是如果这是您的论点,那么删除赋值运算符是否也应该取消聚合?
    • @PatrickFromberg “更广泛的东西。删除的 ctor 也将取消聚合” 抱歉,我不明白这部分。比什么更广泛? “不能通过聚合初始化意外创建副本” 您的意思是手动将每个成员输入到大括号初始化列表中? “你仍然可以有目的地这样做”但是,如果复制 ctor 被删除了怎么办?
    • @HolyBlackCat。创建一个没有复制 ctor 但聚合初始化的相同副本是一项艰巨的工作,因为您必须将所有成员添加到初始化列表中,并且必须以正确的顺序进行。因此不可能偶然发生。但是,对于赋值运算符,它实际上可能会像使用复制 ctor 一样容易意外发生。因此,我认为复制 ctor 和赋值运算符都应该不聚合或都不应该不聚合。
    • @PatrickFromberg 老实说,我从未见过具有自定义复制/移动分配且没有用户定义构造函数的类,所以我认为大多数时候它不应该有所作为。跨度>
    猜你喜欢
    • 1970-01-01
    • 2019-12-07
    • 2014-07-25
    • 2011-06-17
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 2014-07-15
    相关资源
    最近更新 更多