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};
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Alexey R.
  • 183
  • 5

1 Answers1

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.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • 11
    Here is the proposal that did it, which includes rationale: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1008r1.pdf – Howard Hinnant Jul 22 '19 at 21:59
  • 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? – Patrick Fromberg Jan 11 '20 at 19:13
  • @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? – HolyBlackCat Jan 11 '20 at 19:49
  • @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. – Patrick Fromberg Jan 11 '20 at 20:31
  • @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. – HolyBlackCat Jan 12 '20 at 13:23