Date: Sun, 21 Aug 2022 11:32:57 -0400
On Sun, Aug 21, 2022 at 7:38 AM Ivan Matek via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
>
>
> On Thu, Aug 18, 2022 at 11:57 PM Drew Gross via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> could be equivalent to
>>
>> struct S {
>> int a;
>> S() /* some tag that designates this constructor as "the aggregate/designated initializer constructor" */ { std::cout << "constructed an S instance: " << a << std::endl; };
>> };
>>
>> int main() {
>> S s = S{.a = 1};
>> };
>>
>>
>
> You are probably right, except no constructor argument signature might be confusing, so maybe
>
> S(auto&&) = match;
> or
> S(auto&&) = agg_like;
I think these are all coming at the problem from the wrong direction.
The core problem is that sometimes users want to default special
member function constructors without inhibiting the type being able to
undergo aggregate initialization.
Pre-C++20, aggregates could have `default`ed constructors. C++20
changed this because this made it needlessly difficult to write empty
types that were not aggregates. One might think that defaulting the
default constructor would render the type no longer an aggregate, but
this was not the case.
And that's kind of the key here. The problem, as originally described,
wasn't that the user defaulted the default constructor. They defaulted
the *copy* constructor. This was necessitated by adding a non-trivial
destructor. Defaulting a copy constructor doesn't mean much for
aggregate initialization, as the copy constructor doesn't conceptually
interfere in that process.
If a type is an aggregate, then the default constructor should not be
present at all. Defaulting the default constructor is how you signal
that the type is deliberately not an aggregate. So it seems to me we
can fix this particular problem by changing the definition of
aggregates again, such that `default`ing copy/move constructors is
fine, but not default constructors.
<std-proposals_at_[hidden]> wrote:
>
>
>
> On Thu, Aug 18, 2022 at 11:57 PM Drew Gross via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> could be equivalent to
>>
>> struct S {
>> int a;
>> S() /* some tag that designates this constructor as "the aggregate/designated initializer constructor" */ { std::cout << "constructed an S instance: " << a << std::endl; };
>> };
>>
>> int main() {
>> S s = S{.a = 1};
>> };
>>
>>
>
> You are probably right, except no constructor argument signature might be confusing, so maybe
>
> S(auto&&) = match;
> or
> S(auto&&) = agg_like;
I think these are all coming at the problem from the wrong direction.
The core problem is that sometimes users want to default special
member function constructors without inhibiting the type being able to
undergo aggregate initialization.
Pre-C++20, aggregates could have `default`ed constructors. C++20
changed this because this made it needlessly difficult to write empty
types that were not aggregates. One might think that defaulting the
default constructor would render the type no longer an aggregate, but
this was not the case.
And that's kind of the key here. The problem, as originally described,
wasn't that the user defaulted the default constructor. They defaulted
the *copy* constructor. This was necessitated by adding a non-trivial
destructor. Defaulting a copy constructor doesn't mean much for
aggregate initialization, as the copy constructor doesn't conceptually
interfere in that process.
If a type is an aggregate, then the default constructor should not be
present at all. Defaulting the default constructor is how you signal
that the type is deliberately not an aggregate. So it seems to me we
can fix this particular problem by changing the definition of
aggregates again, such that `default`ing copy/move constructors is
fine, but not default constructors.
Received on 2022-08-21 15:33:15