Initialisation of aggregate with default constructor deleted in c++20 [duplicate]
Asked Answered
T

1

8

There is a struct containing POD and default constructor deleted. Trying to aggregate-initalize an instance of the struct results in compilation error in g++9.1 when compiled with -std=c++2a. The same code compiles fine with -std=c++17.

https://godbolt.org/z/xlRHLL

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

int main()
{
    S s {.a = 0};
}
Tribune answered 22/7, 2019 at 21:8 Comment(0)
C
14

Your struct is not an aggregate since C++20.

The definition of aggregate was changed once again:

cppreference

An aggregate is one of the following types:

  • ...

  • class type (typically, struct or union), that has

    • ...

    • no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
      (since C++17) (until C++20)

    • no user-declared or inherited constructors
      (since C++20)

IMO, this fixes a defect in the language. Being able to construct (with aggregate initializaton) objects with deleted or inaccessible constructors doesn't look right to me.

Cultism answered 22/7, 2019 at 21:57 Comment(5)
Here is the proposal that did it, which includes rationale: open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1008r1.pdfSparkie
Sure, aggregate initialisation should not allow accidentally circumventing deleted constructors. But this is not what the change in c++20 does. It does something much broader. A deleted ctor will also unaggregate. But ok, I can see why. For e.g. if your copy ctor is deleted, then you cannot accidentally create a copy via aggregate initizlisation, but you still can do it purposefully and it seems you do not want that either. Ok, but if this is your argument, then deleting an assignment operator should also unaggregate the aggregate or not?Sneaker
@PatrickFromberg "something much broader. A deleted ctor will also unaggregate" Sorry, I don't understand this part. Broader than what? "cannot accidentally create a copy via aggregate initizlisation" You mean by manually typing each member into the brace-init-list? "you still can do it purposefully" But how, if the copy ctor is deleted?Cultism
@HolyBlackCat. Creating an identical copy without copy ctor but aggregate initizllisation instead is hard work because you have to add all members into the initialisation list and you have to do it in the right order. Hence cannot happen accidentally. With the assignment operator though, it actually can happen accidentally almost as easy as with the copy ctor. Hence I believe that copy ctor and assignment operator should both unaggreate or should both not unaggregate.Sneaker
@PatrickFromberg Honestly, I've never seen a class with a custom copy/move assignment and no user-defined constructors, so I think it shouldn't make a difference most of the time.Cultism

© 2022 - 2024 — McMap. All rights reserved.