In short, why the code below behaves like described in the comments?
struct A
{
A() = delete;
//A(const A&) {} // uncommenting this...
};
int main()
{
A a{}; // ... breaks this
//A(); // this fails in either case because of `A() = delete;` only
}
What part of the standard (or at least a page on cppreference) should I look at to understand this?
However, writing A(const A&) = default;
instead of //A(const A&) {}
doesn't break A a{};
. What about this? I think the underlying cause is the same, but a word from who really knows C++ is better than what I think.
Without the user-provided copy constructor, A
is an aggregate. Yes, even though we deleted the default constructor. It's something that was addressed in C++20.
So, prior to C++20, A a{};
is aggregate initialization, and so doesn't use the deleted constructor. When you uncomment the copy constructor, A
stops being an aggregate, thus turning the aggregate initialization into value initialization. So the initialization of a
will attempt to call the deleted constructor.
To divine the meaning of an initializer from the standard, one typically starts at [dcl.init]/16. Going through the bullets, one can find how the properties of the initializer (when matched with the properties of the types in question) will affect the way initialization occurs.