Date: Tue, 11 Jul 2023 12:11:34 +0100
On Tue, 11 Jul 2023 at 11:17, Ofek Shilon <ofekshilon_at_[hidden]> wrote:
> Thanks for the prompt reply!
>
> On Tue, 11 Jul 2023 at 12:53, Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>>
>> Why should Thingy3() = default; give you that behaviour? It's still
>> trivial and it is noexcept. Why should it prevent Thingy3() from zeroing
>> the members?
>>
> The phrasing of this question assumes zeroing the members is some natural
> default and deviating from it requires justification. I believe in C++ it's
> the other way around: you don't pay for what you don't use, so me & quite a
> few people I talked to would expect `= default` to consistently not
> initialize the members, in all initialization forms.
>
But value-initialization zeros things, just like:
int i = int();
If you don't want that, don't use value-init:
int i;
Thingy1 t1;
Thingy3 t3;
The point is that when you do value-init **you are using** the zero-fill
feature, so **you pay for it**.
If you don't want to pay for it, don't use it. You have the choice.
I wish people would stop quoting "you don't pay for what you don't use" as
if it meant you never pay for anything, as though every operation must use
as few instructions as possible, even if that changes the meaning of the
code. I'm sorry you and the people you've talked to are surprised about
what value-initialization does, but that isn't a reason to change how it
works.
> One could just as well ask: "Why should `=default` prevent `Thingy3 t3;`
> from zeroing the members?" - except that it does, and it is very natural
> to expect consistent impact of `=default`.
>
>>
>> If defining it as defaulted behaved how you want, then there would be no
>> way to say "it's default constructible, but I still want it to be trivial".
>> If you do want it to be non-trivial, you can already do that, as you did
>> for Thingy2.
>>
> Not sure I understand this, and if I do - not sure I agree. If you want to
> say "it's default constructible, but the ctor zeros members" (is that what
> you mean by 'trivial'?) then there certainly is a way to express it: just
> write a default ctor that zeros the members.
>
No, that would not be a trivial constructor.
https://en.cppreference.com/w/cpp/language/default_constructor#Trivial_default_constructor
Your suggestion would **remove** functionality from the language. It would
no longer be possible to have a class with a user-declared copy/move/other
constructor and a trivial default constructor, so you would have to pay for
functionality (non-trivial default constructor) that you don't want.
As currently defined, C++ allows you to do this:
struct Thingy4 {
Thingy4() = default;
Thingy4(int);
};
static_assert( std::is_trivially_default_constructible_v<Thingy4> );
The default constructor has to be user-declared because of the
user-provided Thingy4(int) ctor, otherwise it has a deleted default ctor.
Your preferred behaviour would remove the ability to write the code above,
because Thingy4() would be non-trivial.
If you want that, you can already do it, we don't need to change
Thingy4()=default to do that:
struct Thingy5 {
Thingy5() {}
Thingy5(int);
};
static_assert( ! std::is_trivially_default_constructible_v<Thingy5> );
> Thanks for the prompt reply!
>
> On Tue, 11 Jul 2023 at 12:53, Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>>
>> Why should Thingy3() = default; give you that behaviour? It's still
>> trivial and it is noexcept. Why should it prevent Thingy3() from zeroing
>> the members?
>>
> The phrasing of this question assumes zeroing the members is some natural
> default and deviating from it requires justification. I believe in C++ it's
> the other way around: you don't pay for what you don't use, so me & quite a
> few people I talked to would expect `= default` to consistently not
> initialize the members, in all initialization forms.
>
But value-initialization zeros things, just like:
int i = int();
If you don't want that, don't use value-init:
int i;
Thingy1 t1;
Thingy3 t3;
The point is that when you do value-init **you are using** the zero-fill
feature, so **you pay for it**.
If you don't want to pay for it, don't use it. You have the choice.
I wish people would stop quoting "you don't pay for what you don't use" as
if it meant you never pay for anything, as though every operation must use
as few instructions as possible, even if that changes the meaning of the
code. I'm sorry you and the people you've talked to are surprised about
what value-initialization does, but that isn't a reason to change how it
works.
> One could just as well ask: "Why should `=default` prevent `Thingy3 t3;`
> from zeroing the members?" - except that it does, and it is very natural
> to expect consistent impact of `=default`.
>
>>
>> If defining it as defaulted behaved how you want, then there would be no
>> way to say "it's default constructible, but I still want it to be trivial".
>> If you do want it to be non-trivial, you can already do that, as you did
>> for Thingy2.
>>
> Not sure I understand this, and if I do - not sure I agree. If you want to
> say "it's default constructible, but the ctor zeros members" (is that what
> you mean by 'trivial'?) then there certainly is a way to express it: just
> write a default ctor that zeros the members.
>
No, that would not be a trivial constructor.
https://en.cppreference.com/w/cpp/language/default_constructor#Trivial_default_constructor
Your suggestion would **remove** functionality from the language. It would
no longer be possible to have a class with a user-declared copy/move/other
constructor and a trivial default constructor, so you would have to pay for
functionality (non-trivial default constructor) that you don't want.
As currently defined, C++ allows you to do this:
struct Thingy4 {
Thingy4() = default;
Thingy4(int);
};
static_assert( std::is_trivially_default_constructible_v<Thingy4> );
The default constructor has to be user-declared because of the
user-provided Thingy4(int) ctor, otherwise it has a deleted default ctor.
Your preferred behaviour would remove the ability to write the code above,
because Thingy4() would be non-trivial.
If you want that, you can already do it, we don't need to change
Thingy4()=default to do that:
struct Thingy5 {
Thingy5() {}
Thingy5(int);
};
static_assert( ! std::is_trivially_default_constructible_v<Thingy5> );
Received on 2023-07-11 11:11:49