Document number: | P0280R0 |
Date: | 2016-02-08 |
Project: | Programming Language C++, Evolution Working Group |
Reply-to: | James Touton <bekenn@gmail.com> |
The following program is ill-formed:
struct S
{
explicit S(int a = 0) : _a{a} { }
int _a;
};
int main()
{
S arr[2] = { S{} }; // error : chosen constructor is explicit in copy-initialization
}
The error occurs when attempting to match a constructor for the second array element of arr
.
This is because aggregate initialization uses copy initialization for unspecified aggregate members (in this case, the second array element).
Even though S's constructor is a default constuctor (thanks to the default argument), it is unavailable to copy initialization because it is marked explicit
.
This was most likely an unintended consequence of the wording for aggregate initialization.
This paper proposes using direct initialization for unspecified aggregate members in this situation.
This change fixes an obscure corner case, causing previously invalid code to become valid. It has no effect on currently valid code.
When an aggregate is initalized by an initializer list, and the initializer list contains fewer items than there are assignable members of the aggregate, the remaining unspecified members are initialized using direct list initialization from an empty list.
All modifications are presented relative to N4567.
Modify §8.5.1 [dcl.init.aggr] paragraph 7:
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its default member initializer (9.2) or, if there is no default member initializer, from an empty initializer list using direct-list-initialization (8.5.4).