Date: Sat, 8 Aug 2020 18:31:50 +0000 (UTC)
Date: Fri, 7 Aug 2020 21:22:45 -0400
From: Jason McKesson <jmckesson_at_[hidden]>
To: std-proposals_at_[hidden]
Subject: Re: [std-proposals] Default assignment operators from
copy/move constructors
Message-ID:
<CANLtd3WeOR0cxt37rs4c-AvuVYWD=q-ZndpFzOrQAECNdVnw=Q_at_[hidden]>
Content-Type: text/plain; charset="UTF-8"
On Fri, Aug 7, 2020 at 2:47 PM Walt Karas via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Friday, August 7, 2020, 1:33:44 PM CDT, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote: On Fri, 7 Aug 2020 at 21:21, Walt Karas via Std-Proposals<std-proposals_at_[hidden]> wrote:
> >
> > On Friday, August 7, 2020, 12:57:08 PM CDT, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote:
> > On Fri, 7 Aug 2020 at 20:47, Walt Karas via Std-Proposals
> > <std-proposals_at_[hidden]> wrote:
> > > You can't do a destroy+placement-new if the placement-new can throw.
> > >
> > > WK: OK, also good point. If the constructor can throw, then conceptually the default assign can be like this: https://godbolt.org/z/jvdf53
> >
> > That approach doesn't work for anything non-trivial, and requires
> > C++20 implicit object creation otherwise.
> >
> > WK: Hmm can you give quick example of a class for which this would not work? Or can you give a smaller reference than two long (and expensive) books?
>
>
> struct X
> {
> std::string str;
> };
>
> This type can *NOT* be memcpyed, and restoring it from raw bytes is
> equally non-doable.
>
> WK: it's true that in general it can't be memcpyed. But, in this case we are guaranteed that only one of the copies will be destroyed, so it seems safe. In the generated assign, the raw data of the instance is copied off, and then copied back, to the original instance address before it is destoyed. I can't think of an example of a class for which this would not be safe.
It doesn't matter if a compiler might successfully permit such code to
"function". The C++ standard declares this code to exhibit undefined
behavior, and that's unlikely to change anytime soon (not for types
with non-trivial copies/moves, at any rate). The most you'd ever see
is some form of destructive-move, and even that is going to, at some
level, require explicit user intervention to enable for types with
non-trivial copies/moves.
WK: Compilers don't generate C++ they generate object code. The C++ code I gave is only supposed do describe how the generated object code would work.
This is not Standard-compliant code:
void g(T &);
void f(T &v)
{
char cpy[sizeof(T)];
std::memcpy(cpy, &v, sizeof(T));
std::memset(&v, 0, sizeof(T));
std::memcpy(&v, cpy, sizeof(T));
g(v);
}
But I can't think of an example of a type T where it wouldn't work. Can you?
From: Jason McKesson <jmckesson_at_[hidden]>
To: std-proposals_at_[hidden]
Subject: Re: [std-proposals] Default assignment operators from
copy/move constructors
Message-ID:
<CANLtd3WeOR0cxt37rs4c-AvuVYWD=q-ZndpFzOrQAECNdVnw=Q_at_[hidden]>
Content-Type: text/plain; charset="UTF-8"
On Fri, Aug 7, 2020 at 2:47 PM Walt Karas via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Friday, August 7, 2020, 1:33:44 PM CDT, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote: On Fri, 7 Aug 2020 at 21:21, Walt Karas via Std-Proposals<std-proposals_at_[hidden]> wrote:
> >
> > On Friday, August 7, 2020, 12:57:08 PM CDT, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote:
> > On Fri, 7 Aug 2020 at 20:47, Walt Karas via Std-Proposals
> > <std-proposals_at_[hidden]> wrote:
> > > You can't do a destroy+placement-new if the placement-new can throw.
> > >
> > > WK: OK, also good point. If the constructor can throw, then conceptually the default assign can be like this: https://godbolt.org/z/jvdf53
> >
> > That approach doesn't work for anything non-trivial, and requires
> > C++20 implicit object creation otherwise.
> >
> > WK: Hmm can you give quick example of a class for which this would not work? Or can you give a smaller reference than two long (and expensive) books?
>
>
> struct X
> {
> std::string str;
> };
>
> This type can *NOT* be memcpyed, and restoring it from raw bytes is
> equally non-doable.
>
> WK: it's true that in general it can't be memcpyed. But, in this case we are guaranteed that only one of the copies will be destroyed, so it seems safe. In the generated assign, the raw data of the instance is copied off, and then copied back, to the original instance address before it is destoyed. I can't think of an example of a class for which this would not be safe.
It doesn't matter if a compiler might successfully permit such code to
"function". The C++ standard declares this code to exhibit undefined
behavior, and that's unlikely to change anytime soon (not for types
with non-trivial copies/moves, at any rate). The most you'd ever see
is some form of destructive-move, and even that is going to, at some
level, require explicit user intervention to enable for types with
non-trivial copies/moves.
WK: Compilers don't generate C++ they generate object code. The C++ code I gave is only supposed do describe how the generated object code would work.
This is not Standard-compliant code:
void g(T &);
void f(T &v)
{
char cpy[sizeof(T)];
std::memcpy(cpy, &v, sizeof(T));
std::memset(&v, 0, sizeof(T));
std::memcpy(&v, cpy, sizeof(T));
g(v);
}
But I can't think of an example of a type T where it wouldn't work. Can you?
Received on 2020-08-08 13:35:16