0

I have a very simple code example. I can compile it in C++17 but cannot in C++20. Why not?

struct S
{
    S(const S&) = delete;
    S( S&& ) = default;

    int k;
    int m;
    int n;
};

int main()
{
    S s1{10, 20, 30};
    return s1.m;
}
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    There is pretty much no legitimate use case for a type with a deleted copy construct and a defaulted move constructor. If the default move (ie: copy) is OK for the object on move, then the object is logically copyable. – Nicol Bolas Aug 15 '21 at 23:08

1 Answers1

5

This is because of P1008, which changed the rule for what qualifies as an aggregate from

no user-provided, explicit, or inherited constructors

to

no user-declared or inherited constructors

Your constructors are user-declared but not user-provided (you declare them, so they're user-declared, but they're defaulted on their initial declaration, so you're not providing a definition for them). In C++17, S is an aggregate. But in C++20, it is not. Because of that, there is no aggregate initialization anymore, so S{10, 20, 30} can only invoke constructors - of which there is no viable one.

If you want this to keep working, you'll have to provide a constructor.

For more details on C++20 changes to aggregates, see my answer here.

Barry
  • 286,269
  • 29
  • 621
  • 977