Topic: Destructive move by base class destructor
Author: David Krauss <potswa@gmail.com>
Date: Sun, 2 Aug 2015 11:28:21 +0800
Raw View
--Apple-Mail=_40843862-0701-4D43-AA95-BE908366CD27
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
Following up on the thread =E2=80=9Cmovable class property,=E2=80=9D here=
=E2=80=99s the beginning of a proposal to use base class destructors as an =
alternative to N4393=E2=80=99s __COOKIE__.
Advantages:
=E2=80=94 No new syntax.
=E2=80=94 Does not treat non-POD members as POD.
=E2=80=94 Handles non-POD members using their actual constructors and destr=
uctors.
=E2=80=94 Does still effectively treat a non-POD derived class as POD, give=
n a suitable POD base.
=E2=80=94 Fully generic implementation of uninitialized_destructive_move.
=E2=80=94 Thrillingly named Sliced destruction. PDF <http://bit.ly/sliced_d=
estruction>.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_40843862-0701-4D43-AA95-BE908366CD27
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D"">Following up on th=
e thread =E2=80=9Cmovable class property,=E2=80=9D here=E2=80=99s the begin=
ning of a proposal to use base class destructors as an alternative to N4393=
=E2=80=99s <font face=3D"Courier" class=3D"">__COOKIE__</font>.<div cl=
ass=3D""><br class=3D""></div><div class=3D"">Advantages:</div><div class=
=3D""><br class=3D""></div><div class=3D"">=E2=80=94 No new syntax.</div><d=
iv class=3D"">=E2=80=94 Does not treat non-POD members as POD.</div><div cl=
ass=3D"">=E2=80=94 Handles non-POD members using their actual constructors =
and destructors.</div><div class=3D"">=E2=80=94 Does still effectively trea=
t a non-POD derived class as POD, given a suitable POD base.</div><div clas=
s=3D"">=E2=80=94 Fully generic implementation of <span style=3D"font-f=
amily: Courier; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-strok=
e-width: initial;" class=3D"">uninitialized_destructive_move</span>.</div><=
div class=3D"">=E2=80=94 Thrillingly named <i class=3D"">Sliced destruction=
</i>. <a href=3D"http://bit.ly/sliced_destruction" class=3D"">PDF</a>.=
</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_40843862-0701-4D43-AA95-BE908366CD27--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 1 Aug 2015 22:05:43 -0700 (PDT)
Raw View
------=_Part_749_1190853496.1438491944110
Content-Type: multipart/alternative;
boundary="----=_Part_750_1068265800.1438491944117"
------=_Part_750_1068265800.1438491944117
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
The problem I see with this is that although it could be "like" memcpy, it=
=20
is not in fact memcpy.
As far as I can tell, this prevents use of realloc.
Arguably, though, we could propose a new function, try_realloc, which would=
=20
fail and not change or move anything, if it fails to enlarge memory in=20
place.
A function like try_realloc would benefit all containers, including those -=
=20
and especially those - that must perform deep copy on reallocation.
Possibly, then - this + try_realloc could get the job sort of done.
But I have another problem with this - which is that it seems to=20
prevent, or make harder, introduction of the feature I *really* want. What=
=20
I *really* want is a standardized rule that would allow the developer to=20
rely on the compiler to automatically mark types is_location_agnostic or=20
is_relocatable. In my opinion, the compiler should do the deduction, and=20
the developer should check the result. This way, the compiler and the=20
developer make each other stronger.
The other way around cannot be done: if we require the developer to do the=
=20
deduction, the compiler can't check the result.
To me, this is *the* core feature for which I want language support. If I=
=20
can't rely on the compiler to help me correctly mark my types, then to me,=
=20
there isn't a major difference to having a standardized property, as=20
opposed to rolling my own. In either case, I won't use it, because it's too=
=20
dangerous. I don't trust myself to not introduce errors if I'm required=20
to manually mark every type.
On Saturday, August 1, 2015 at 9:28:31 PM UTC-6, David Krauss wrote:
> Following up on the thread =E2=80=9Cmovable class property,=E2=80=9D here=
=E2=80=99s the beginning=20
> of a proposal to use base class destructors as an alternative to N4393=E2=
=80=99s=20
> __COOKIE__.
>
> Advantages:
>
> =E2=80=94 No new syntax.
> =E2=80=94 Does not treat non-POD members as POD.
> =E2=80=94 Handles non-POD members using their actual constructors and des=
tructors.
> =E2=80=94 Does still effectively treat a non-POD derived class as POD, gi=
ven a=20
> suitable POD base.
> =E2=80=94 Fully generic implementation of uninitialized_destructive_move.
> =E2=80=94 Thrillingly named *Sliced destruction*. PDF=20
> <http://bit.ly/sliced_destruction>.
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_750_1068265800.1438491944117
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>The problem=C2=A0I see with=C2=A0this is that althoug=
h it could be "like" memcpy, it is not in fact memcpy.</div><div>=
<br></div><div>As far as I can tell, this prevents use of <font face=3D"cou=
rier new,monospace">realloc</font>.</div><div><br></div><div>Arguably, thou=
gh, we could=C2=A0propose a new function,=C2=A0<font face=3D"courier new,mo=
nospace">try_realloc</font>, which would fail and not change or move=C2=A0a=
nything, if it fails to enlarge memory in place.</div><div><br></div><div>A=
function like <font face=3D"courier new,monospace">try_realloc</font> woul=
d benefit all containers, including those - and especially those - that mus=
t perform deep copy on reallocation.</div><div><br></div><div>Possibly, the=
n -=C2=A0this + <font face=3D"courier new,monospace">try_realloc</font> cou=
ld get the job=C2=A0sort of=C2=A0done.</div><div><br></div><div>But I have =
another problem with this -=C2=A0which is that it seems to prevent,=C2=A0or=
make harder,=C2=A0introduction of the feature I <em>really</em> want.=C2=
=A0What I <em>really</em> want=C2=A0is a standardized rule that would allow=
the developer to rely on the compiler to automatically mark types <font fa=
ce=3D"courier new,monospace">is_location_agnostic</font> or <font face=3D"c=
ourier new,monospace">is_relocatable</font>. In my opinion, the compiler sh=
ould do the deduction, and the developer should check the result. This way,=
the compiler and the developer make each other stronger.</div><div><br></d=
iv><div>The other way around cannot be done: if we require the developer to=
do the deduction, the compiler can't check the result.</div><div><br><=
/div><div>To me, this is <em>the</em> core feature for which I=C2=A0want la=
nguage support. If I can't rely on the compiler to help me correctly ma=
rk my types,=C2=A0then to me, there isn't a major difference to having =
a standardized property, as opposed to rolling my own. In either case, I=C2=
=A0won't use it, because it's too dangerous.=C2=A0I don't trust=
myself to not introduce errors if I'm required to=C2=A0manually mark e=
very type.</div><div><br></div><div><br>On Saturday, August 1, 2015 at 9:28=
:31 PM UTC-6, David Krauss wrote:</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb=
(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div st=
yle=3D"-ms-word-wrap: break-word;">Following up on the thread =E2=80=9Cmova=
ble class property,=E2=80=9D here=E2=80=99s the beginning of a proposal to =
use base class destructors as an alternative to N4393=E2=80=99s=C2=A0<font =
face=3D"Courier">__COOKIE__</font>.<div><br></div><div>Advantages:</div><di=
v><br></div><div>=E2=80=94 No new syntax.</div><div>=E2=80=94 Does not trea=
t non-POD members as POD.</div><div>=E2=80=94 Handles non-POD members using=
their actual constructors and destructors.</div><div>=E2=80=94 Does still =
effectively treat a non-POD derived class as POD, given a suitable POD base=
..</div><div>=E2=80=94 Fully generic implementation of=C2=A0<span style=3D"f=
ont-family: Courier;">uninitialized_destructive_<wbr>move</span>.</div><div=
>=E2=80=94 Thrillingly named <i>Sliced destruction</i>.=C2=A0<a onmousedown=
=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fbit.ly%2Fsl=
iced_destruction\46sa\75D\46sntz\0751\46usg\75AFQjCNH2I6F4650PvwqT2k6CD1tqR=
x54yg';return true;" onclick=3D"this.href=3D'http://www.google.com/=
url?q\75http%3A%2F%2Fbit.ly%2Fsliced_destruction\46sa\75D\46sntz\0751\46usg=
\75AFQjCNH2I6F4650PvwqT2k6CD1tqRx54yg';return true;" href=3D"http://bit=
..ly/sliced_destruction" target=3D"_blank" rel=3D"nofollow">PDF</a>.</div><d=
iv><br></div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_750_1068265800.1438491944117--
------=_Part_749_1190853496.1438491944110--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 01 Aug 2015 23:22:52 -0700
Raw View
On Saturday 01 August 2015 22:05:43 denis bider wrote:
> As far as I can tell, this prevents use of realloc.
>
> Arguably, though, we could propose a new function, try_realloc, which would
> fail and not change or move anything, if it fails to enlarge memory in
> place.
>
> A function like try_realloc would benefit all containers, including those -
> and especially those - that must perform deep copy on reallocation.
Right, we need that function anyway, but it's not completely enough.
A realloc() function that manipulated memory mappings could keep an existing
page of allocation and simply remap it elsewhere to enlarge, with no copy
required. try_realloc + copy can't do zero copies.
> Possibly, then - this + try_realloc could get the job sort of done.
>
> But I have another problem with this - which is that it seems to
> prevent, or make harder, introduction of the feature I *really* want. What
> I *really* want is a standardized rule that would allow the developer to
> rely on the compiler to automatically mark types is_location_agnostic or
> is_relocatable. In my opinion, the compiler should do the deduction, and
> the developer should check the result. This way, the compiler and the
> developer make each other stronger.
For that, we need something that may have non-zero false negatives, but it
cannot have any false positive, for any reason. Can you guarantee that the
compiler would never think a type is relocatable when it really isn't?
> To me, this is *the* core feature for which I want language support. If I
> can't rely on the compiler to help me correctly mark my types, then to me,
> there isn't a major difference to having a standardized property, as
> opposed to rolling my own. In either case, I won't use it, because it's too
> dangerous. I don't trust myself to not introduce errors if I'm required
> to manually mark every type.
For me, it isn't. The core feature for me is the ability to memcpy or realloc
confidently. But it's an optimisation, so if I miss a type or two, the worst
case scanerio is that it's slightly slower than it could have been.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 2 Aug 2015 14:19:02 +0800
Raw View
--Apple-Mail=_082E3B14-E2E6-4F82-B1EB-16B014C84BE1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9302, at 1:05 PM, denis bider <isocppgroup@denis=
bider.com> wrote:
>=20
> The problem I see with this is that although it could be "like" memcpy, i=
t is not in fact memcpy.
If you have a trivially movable base subobject B, and no other bytes in the=
object, then this constructor does a memcpy and nothing else:
D::D( B && b ) : B{ std::move( b ) } {}
If you call this constructor in a loop, then nothing is stopping the compil=
er from detecting that it=E2=80=99s nothing but a sequence of memcpy calls,=
and merging them into one big memcpy. (I=E2=80=99m not checking, right now=
, whether such optimizations are actually done. It would be surprising if i=
t were implemented by all C++ compilers, or none.)
Note, the compiler can use memcpy even in cases where nothing is officially=
trivial at all. It can do anything that behaves correctly in the end.
> As far as I can tell, this prevents use of realloc.
I=E2=80=99d rather write a semantically correct program and let the optimiz=
er make it fast.
> But I have another problem with this - which is that it seems to prevent,=
or make harder, introduction of the feature I really want. What I really w=
ant is a standardized rule that would allow the developer to rely on the co=
mpiler to automatically mark types is_location_agnostic or is_relocatable. =
In my opinion, the compiler should do the deduction, and the developer shou=
ld check the result. This way, the compiler and the developer make each oth=
er stronger.
The programmer marks pointers as relocatable or (potentially) not, then the=
compiler summarizes those attributes, and the programmer uses the summary =
to decide whether or not to call realloc? No thanks.
> The other way around cannot be done: if we require the developer to do th=
e deduction, the compiler can't check the result.
>=20
> To me, this is the core feature for which I want language support. If I c=
an't rely on the compiler to help me correctly mark my types, then to me, t=
here isn't a major difference to having a standardized property, as opposed=
to rolling my own. In either case, I won't use it, because it's too danger=
ous. I don't trust myself to not introduce errors if I'm required to manual=
ly mark every type.
I don=E2=80=99t want any properties or traits. I just want a way to elimina=
te wasted effort where the last few actions of the move constructor are can=
celled by the first few actions of the destructor.
I also don=E2=80=99t particularly like fiddling with object representations=
.. It=E2=80=99s not a very forward-looking approach.
So, my proposal defines a bare minimum one trait, which enables safe suppor=
t for all types regardless of triviality.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_082E3B14-E2E6-4F82-B1EB-16B014C84BE1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=
=E2=80=9302, at 1:05 PM, denis bider <<a href=3D"mailto:isocppgroup@deni=
sbider.com" class=3D"">isocppgroup@denisbider.com</a>> wrote:</div><br c=
lass=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=
=3D""><div class=3D"">The problem I see with this is that althoug=
h it could be "like" memcpy, it is not in fact memcpy.</div></div></div></b=
lockquote><div><br class=3D""></div><div>If you have a trivially movable ba=
se subobject <font face=3D"Courier" class=3D"">B</font>, and no other bytes=
in the object, then this constructor does a <font face=3D"Courier" class=
=3D"">memcpy</font> and nothing else:</div><div><br class=3D""></div><div><=
font face=3D"Courier" class=3D"">D::D( B && b ) : B{ std::move( b )=
} {}</font></div><div><br class=3D""></div><div>If you call this construct=
or in a loop, then nothing is stopping the compiler from detecting that it=
=E2=80=99s nothing but a sequence of <font face=3D"Courier" class=3D"">memc=
py</font> calls, and merging them into one big <font face=3D"Courier" class=
=3D"">memcpy</font>. (I=E2=80=99m not checking, right now, whether such opt=
imizations are actually done. It would be surprising if it were implemented=
by all C++ compilers, or none.)</div><div><br class=3D""></div><div>Note, =
the compiler can use <font face=3D"Courier" class=3D"">memcpy</font> even i=
n cases where nothing is officially trivial at all. It can do anything that=
behaves correctly in the end.</div><br class=3D""><blockquote type=3D"cite=
" class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">As far as I can te=
ll, this prevents use of <font face=3D"courier new,monospace" class=3D"">re=
alloc</font>.</div><div class=3D""></div></div></blockquote><div><br class=
=3D""></div><div>I=E2=80=99d rather write a semantically correct program an=
d let the optimizer make it fast.</div><br class=3D""><blockquote type=3D"c=
ite" class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">But I have anot=
her problem with this - which is that it seems to prevent, or mak=
e harder, introduction of the feature I <em class=3D"">really</em> wan=
t. What I <em class=3D"">really</em> want is a standardized rule =
that would allow the developer to rely on the compiler to automatically mar=
k types <font face=3D"courier new,monospace" class=3D"">is_location_agnosti=
c</font> or <font face=3D"courier new,monospace" class=3D"">is_relocatable<=
/font>. In my opinion, the compiler should do the deduction, and the develo=
per should check the result. This way, the compiler and the developer make =
each other stronger.</div><div class=3D""></div></div></blockquote><div><br=
class=3D""></div><div>The programmer marks pointers as relocatable or (pot=
entially) not, then the compiler summarizes those attributes, and the progr=
ammer uses the summary to decide whether or not to call <font face=3D"Couri=
er" class=3D"">realloc</font>? No thanks.</div><br class=3D""><blockquote t=
ype=3D"cite" class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">The oth=
er way around cannot be done: if we require the developer to do the deducti=
on, the compiler can't check the result.</div><div class=3D""><br class=3D"=
"></div><div class=3D"">To me, this is <em class=3D"">the</em> core feature=
for which I want language support. If I can't rely on the compiler to=
help me correctly mark my types, then to me, there isn't a major diff=
erence to having a standardized property, as opposed to rolling my own. In =
either case, I won't use it, because it's too dangerous. I don't =
trust myself to not introduce errors if I'm required to manually mark =
every type.</div></div></blockquote><br class=3D""></div><div>I don=E2=80=
=99t want any properties or traits. I just want a way to eliminate wasted e=
ffort where the last few actions of the move constructor are cancelled by t=
he first few actions of the destructor.</div><div><br class=3D""></div><div=
>I also don=E2=80=99t particularly like fiddling with object representation=
s. It=E2=80=99s not a very forward-looking approach.</div><div><br class=3D=
""></div><div>So, my proposal defines a bare minimum one trait, which enabl=
es <i class=3D"">safe</i> support for all types regardless of triviality.</=
div><div><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_082E3B14-E2E6-4F82-B1EB-16B014C84BE1--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 2 Aug 2015 00:28:57 -0700 (PDT)
Raw View
------=_Part_773_95244904.1438500538089
Content-Type: multipart/alternative;
boundary="----=_Part_774_831499284.1438500538090"
------=_Part_774_831499284.1438500538090
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> The programmer marks pointers as relocatable or (potentially) not,
> then the compiler summarizes those attributes, and the
> programmer uses the summary to decide whether
> or not to call realloc? No thanks.
What? I can't imagine how you thought that could be what I meant.
No, what I meant is this:
class Str relocatable { (insert implementation) };
struct A { Str x; };
static_assert(std::is_relocatable<A>::value, "");
This is the feature I need.
If I implement my own basic types that are relocatable or location=20
agnostic, I need the compiler to infer that my other types, which:
- derive from or aggregate my basic types, and
- have an implicit or defaulted copy constructor,
are also relocatable (or location agnostic).
That's the feature I need.
I really don't give a rat's rear end if this feature is not made available.=
=20
If I cannot count on the compiler's support, then any other "support" for=
=20
this means nothing to me. Zero.
On Sunday, August 2, 2015 at 12:26:01 AM UTC-6, David Krauss wrote:
>
> On 2015=E2=80=9308=E2=80=9302, at 1:05 PM, denis bider <isocp...@denisbid=
er.com=20
> <javascript:>> wrote:
>
> The problem I see with this is that although it could be "like" memcpy, i=
t=20
> is not in fact memcpy.
>
>
> If you have a trivially movable base subobject B, and no other bytes in=
=20
> the object, then this constructor does a memcpy and nothing else:
>
> D::D( B && b ) : B{ std::move( b ) } {}
>
> If you call this constructor in a loop, then nothing is stopping the=20
> compiler from detecting that it=E2=80=99s nothing but a sequence of memcp=
y calls,=20
> and merging them into one big memcpy. (I=E2=80=99m not checking, right no=
w,=20
> whether such optimizations are actually done. It would be surprising if i=
t=20
> were implemented by all C++ compilers, or none.)
>
> Note, the compiler can use memcpy even in cases where nothing is=20
> officially trivial at all. It can do anything that behaves correctly in t=
he=20
> end.
>
> As far as I can tell, this prevents use of realloc.
>
>
> I=E2=80=99d rather write a semantically correct program and let the optim=
izer make=20
> it fast.
>
> But I have another problem with this - which is that it seems to=20
> prevent, or make harder, introduction of the feature I *really*=20
> want. What I *really* want is a standardized rule that would allow the=20
> developer to rely on the compiler to automatically mark types=20
> is_location_agnostic or is_relocatable. In my opinion, the compiler=20
> should do the deduction, and the developer should check the result. This=
=20
> way, the compiler and the developer make each other stronger.
>
>
> The programmer marks pointers as relocatable or (potentially) not, then=
=20
> the compiler summarizes those attributes, and the programmer uses the=20
> summary to decide whether or not to call realloc? No thanks.
>
> The other way around cannot be done: if we require the developer to do th=
e=20
> deduction, the compiler can't check the result.
>
> To me, this is *the* core feature for which I want language support. If I=
=20
> can't rely on the compiler to help me correctly mark my types, then to me=
,=20
> there isn't a major difference to having a standardized property, as=20
> opposed to rolling my own. In either case, I won't use it, because it's t=
oo=20
> dangerous. I don't trust myself to not introduce errors if I'm required=
=20
> to manually mark every type.
>
>
> I don=E2=80=99t want any properties or traits. I just want a way to elimi=
nate=20
> wasted effort where the last few actions of the move constructor are=20
> cancelled by the first few actions of the destructor.
>
> I also don=E2=80=99t particularly like fiddling with object representatio=
ns. It=E2=80=99s=20
> not a very forward-looking approach.
>
> So, my proposal defines a bare minimum one trait, which enables *safe*=20
> support for all types regardless of triviality.
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_774_831499284.1438500538090
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> The programmer marks pointers as relocatable or =
(potentially) not,</div><div>> then the compiler summarizes those attrib=
utes, and the</div><div>> programmer uses the summary to decide whether<=
/div><div>> or not to call <font face=3D"Courier">realloc</font>? No tha=
nks.</div><div><br></div><div>What? I can't imagine how you thought tha=
t could be what I meant.</div><div><br></div><div>No, what I meant is=C2=A0=
this:</div><div><br></div><div><br></div><div><font face=3D"courier new,mon=
ospace">class Str relocatable { (insert implementation) };</font></div><div=
><font face=3D"courier new,monospace"><br></font></div><div><font face=3D"c=
ourier new,monospace">struct A { Str x; };</font></div><div><font face=3D"c=
ourier new,monospace"><br></font></div><div><font face=3D"courier new,monos=
pace">static_assert(std::is_relocatable<A>::value, "");</fo=
nt></div><div><br></div><div><br></div><div>This is the feature I need.</di=
v><div><br></div><div>If I implement my own basic types that are relocatabl=
e or location agnostic, I need the compiler to infer that my other types, w=
hich:</div><div><br></div><div>- derive from or aggregate my basic types,=
=C2=A0and</div><div><br></div><div>- have an implicit or defaulted copy con=
structor,</div><div><br></div><div>are also relocatable (or location agnost=
ic).</div><div><br></div><div>That's the feature I need.</div><div><br>=
</div><div>I really don't give a rat's rear end if this feature is =
not made available. If I cannot count on the compiler's support, then a=
ny other "support" for this means nothing to me. Zero.</div><div>=
<br></div><div><br><br>On Sunday, August 2, 2015 at 12:26:01 AM UTC-6, Davi=
d Krauss wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px=
0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); b=
order-left-width: 1px; border-left-style: solid;"><div style=3D"-ms-word-wr=
ap: break-word;"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9308=
=E2=80=9302, at 1:05 PM, denis bider <<a onmousedown=3D"this.href=3D'=
;javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;;return true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf=
-obfuscated-mailto=3D"_E_jnLEuDwAJ">isocp...@denisbider.com</a>> wrote:<=
/div><br><div><div dir=3D"ltr"><div>The problem=C2=A0I see with=C2=A0this i=
s that although it could be "like" memcpy, it is not in fact memc=
py.</div></div></div></blockquote><div><br></div><div>If you have a trivial=
ly movable base subobject <font face=3D"Courier">B</font>, and no other byt=
es in the object, then this constructor does a <font face=3D"Courier">memcp=
y</font> and nothing else:</div><div><br></div><div><font face=3D"Courier">=
D::D( B && b ) : B{ std::move( b ) } {}</font></div><div><br></div>=
<div>If you call this constructor in a loop, then nothing is stopping the c=
ompiler from detecting that it=E2=80=99s nothing but a sequence of <font fa=
ce=3D"Courier">memcpy</font> calls, and merging them into one big <font fac=
e=3D"Courier">memcpy</font>. (I=E2=80=99m not checking, right now, whether =
such optimizations are actually done. It would be surprising if it were imp=
lemented by all C++ compilers, or none.)</div><div><br></div><div>Note, the=
compiler can use <font face=3D"Courier">memcpy</font> even in cases where =
nothing is officially trivial at all. It can do anything that behaves corre=
ctly in the end.</div><br><blockquote type=3D"cite"><div dir=3D"ltr"><div>A=
s far as I can tell, this prevents use of <font face=3D"courier new,monospa=
ce">realloc</font>.</div><div></div></div></blockquote><div><br></div><div>=
I=E2=80=99d rather write a semantically correct program and let the optimiz=
er make it fast.</div><br><blockquote type=3D"cite"><div dir=3D"ltr"><div>B=
ut I have another problem with this -=C2=A0which is that it seems to preven=
t,=C2=A0or make harder,=C2=A0introduction of the feature I <em>really</em> =
want.=C2=A0What I <em>really</em> want=C2=A0is a standardized rule that wou=
ld allow the developer to rely on the compiler to automatically mark types =
<font face=3D"courier new,monospace">is_location_agnostic</font> or <font f=
ace=3D"courier new,monospace">is_relocatable</font>. In my opinion, the com=
piler should do the deduction, and the developer should check the result. T=
his way, the compiler and the developer make each other stronger.</div><div=
></div></div></blockquote><div><br></div><div>The programmer marks pointers=
as relocatable or (potentially) not, then the compiler summarizes those at=
tributes, and the programmer uses the summary to decide whether or not to c=
all <font face=3D"Courier">realloc</font>? No thanks.</div><br><blockquote =
type=3D"cite"><div dir=3D"ltr"><div>The other way around cannot be done: if=
we require the developer to do the deduction, the compiler can't check=
the result.</div><div><br></div><div>To me, this is <em>the</em> core feat=
ure for which I=C2=A0want language support. If I can't rely on the comp=
iler to help me correctly mark my types,=C2=A0then to me, there isn't a=
major difference to having a standardized property, as opposed to rolling =
my own. In either case, I=C2=A0won't use it, because it's too dange=
rous.=C2=A0I don't trust myself to not introduce errors if I'm requ=
ired to=C2=A0manually mark every type.</div></div></blockquote><br></div><d=
iv>I don=E2=80=99t want any properties or traits. I just want a way to elim=
inate wasted effort where the last few actions of the move constructor are =
cancelled by the first few actions of the destructor.</div><div><br></div><=
div>I also don=E2=80=99t particularly like fiddling with object representat=
ions. It=E2=80=99s not a very forward-looking approach.</div><div><br></div=
><div>So, my proposal defines a bare minimum one trait, which enables <i>sa=
fe</i> support for all types regardless of triviality.</div><div><br></div>=
</div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_774_831499284.1438500538090--
------=_Part_773_95244904.1438500538089--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 2 Aug 2015 15:52:14 +0800
Raw View
--Apple-Mail=_67402EF2-17C3-46B5-BEF5-259972CCE5C5
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9302, at 3:28 PM, denis bider <isocppgroup@denis=
bider.com> wrote:
>=20
> > The programmer marks pointers as relocatable or (potentially) not,
> > then the compiler summarizes those attributes, and the
> > programmer uses the summary to decide whether
> > or not to call realloc? No thanks.
>=20
> What? I can't imagine how you thought that could be what I meant.
>=20
> This is the feature I need.
>=20
> If I implement my own basic types that are relocatable or location agnost=
ic,
=E2=80=A6 presumably marking them as such=E2=80=A6
> I need the compiler to infer that my other types, which:
=E2=80=A6 summarizing the attributes=E2=80=A6
> - derive from or aggregate my basic types, and
>=20
> - have an implicit or defaulted copy constructor,
>=20
> are also relocatable (or location agnostic).
>=20
> That's the feature I need.
=E2=80=A6 then what happens? You call realloc or memcpy, right?
> I really don't give a rat's rear end if this feature is not made availabl=
e. If I cannot count on the compiler's support, then any other "support" fo=
r this means nothing to me. Zero.
I think this discussion is off topic for this thread. It sounds like you wa=
nt something like a combination of is_trivially_move_constructible and a cu=
stom contains_self_references trait. It=E2=80=99s not clear what you want t=
o do with types that don=E2=80=99t realloc.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_67402EF2-17C3-46B5-BEF5-259972CCE5C5
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=
=E2=80=9302, at 3:28 PM, denis bider <<a href=3D"mailto:isocppgroup@deni=
sbider.com" class=3D"">isocppgroup@denisbider.com</a>> wrote:</div><br c=
lass=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><div class=3D"">> The programmer marks pointers=
as relocatable or (potentially) not,</div><div class=3D"">> then the co=
mpiler summarizes those attributes, and the</div><div class=3D"">> progr=
ammer uses the summary to decide whether</div><div class=3D"">> or not t=
o call<span class=3D"Apple-converted-space"> </span><font face=3D"Cour=
ier" class=3D"">realloc</font>? No thanks.</div><div class=3D""><br class=
=3D""></div><div class=3D"">What? I can't imagine how you thought that coul=
d be what I meant.</div><div class=3D""><br class=3D""></div><div class=3D"=
">This is the feature I need.</div><div class=3D""><br class=3D""></div><di=
v class=3D"">If I implement my own basic types that are relocatable or loca=
tion agnostic, </div></div></div></blockquote><div><br class=3D""></div><di=
v>=E2=80=A6 presumably marking them as such=E2=80=A6</div><br class=3D""><b=
lockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><div class=3D"">I need the compiler to infer that =
my other types, which:</div><div class=3D""></div></div></div></blockquote>=
<div><br class=3D""></div><div>=E2=80=A6 summarizing the attributes=E2=80=
=A6</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"=
"><div dir=3D"ltr" style=3D"font-family: Helvetica; font-size: 12px; font-s=
tyle: normal; font-variant: normal; font-weight: normal; letter-spacing: no=
rmal; line-height: normal; orphans: auto; text-align: start; text-indent: 0=
px; text-transform: none; white-space: normal; widows: auto; word-spacing: =
0px; -webkit-text-stroke-width: 0px;" class=3D""><div class=3D"">- derive f=
rom or aggregate my basic types, and</div><div class=3D""><br class=3D=
""></div><div class=3D"">- have an implicit or defaulted copy constructor,<=
/div><div class=3D""><br class=3D""></div><div class=3D"">are also relocata=
ble (or location agnostic).</div><div class=3D""><br class=3D""></div><div =
class=3D"">That's the feature I need.</div><div class=3D""></div></div></di=
v></blockquote><div><br class=3D""></div><div>=E2=80=A6 then what happens? =
You call <font face=3D"Courier" class=3D"">realloc</font> or <font face=3D"=
Courier" class=3D"">memcpy</font>, right?</div><br class=3D""><blockquote t=
ype=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" style=3D"font-fami=
ly: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; f=
ont-weight: normal; letter-spacing: normal; line-height: normal; orphans: a=
uto; text-align: start; text-indent: 0px; text-transform: none; white-space=
: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"=
class=3D""><div class=3D"">I really don't give a rat's rear end if this fe=
ature is not made available. If I cannot count on the compiler's support, t=
hen any other "support" for this means nothing to me. Zero.</div></div></di=
v></blockquote></div><br class=3D""><div class=3D"">I think this discussion=
is off topic for this thread. It sounds like you want something like a com=
bination of <font face=3D"Courier" class=3D"">is_trivially_move_constr=
uctible</font> and a custom <font face=3D"Courier" class=3D"">contains=
_self_references</font> trait. It=E2=80=99s not clear what you want to do w=
ith types that <i class=3D"">don=E2=80=99t</i> <font face=3D"Courier" =
class=3D"">realloc</font>.</div><div class=3D""><br class=3D""></div></body=
></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_67402EF2-17C3-46B5-BEF5-259972CCE5C5--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 2 Aug 2015 01:20:12 -0700 (PDT)
Raw View
------=_Part_871_2049778846.1438503612495
Content-Type: multipart/alternative;
boundary="----=_Part_872_1020773887.1438503612495"
------=_Part_872_1020773887.1438503612495
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> =E2=80=A6 then what happens? You call realloc or memcpy, right?
I store the various types in containers; standard or otherwise. The=20
containers call realloc or memcpy.
> It sounds like you want something like a combination of
> is_trivially_move_constructible and a
> custom contains_self_references trait.
What I want is the is_trivially_destructive_movable trait - by whichever of=
=20
its names (is_relocatable, is_location_agnostic).
As far as I can see, they are all the same trait.
This is on topic for this thread, because your proposal attempts to fill=20
this niche in a fairly horrendous way, which would prevent the definition=
=20
of a proper trait with compiler support for inferring it.
On Sunday, August 2, 2015 at 1:52:33 AM UTC-6, David Krauss wrote:
>
> On 2015=E2=80=9308=E2=80=9302, at 3:28 PM, denis bider <isocp...@denisbid=
er.com=20
> <javascript:>> wrote:
>
> > The programmer marks pointers as relocatable or (potentially) not,
> > then the compiler summarizes those attributes, and the
> > programmer uses the summary to decide whether
> > or not to call realloc? No thanks.
>
> What? I can't imagine how you thought that could be what I meant.
>
> This is the feature I need.
>
> If I implement my own basic types that are relocatable or location=20
> agnostic,=20
>
>
> =E2=80=A6 presumably marking them as such=E2=80=A6
>
> I need the compiler to infer that my other types, which:
>
>
> =E2=80=A6 summarizing the attributes=E2=80=A6
>
> - derive from or aggregate my basic types, and
>
> - have an implicit or defaulted copy constructor,
>
> are also relocatable (or location agnostic).
>
> That's the feature I need.
>
>
> =E2=80=A6 then what happens? You call realloc or memcpy, right?
>
> I really don't give a rat's rear end if this feature is not made=20
> available. If I cannot count on the compiler's support, then any other=20
> "support" for this means nothing to me. Zero.
>
>
> I think this discussion is off topic for this thread. It sounds like you=
=20
> want something like a combination of is_trivially_move_constructible and=
=20
> a custom contains_self_references trait. It=E2=80=99s not clear what you =
want to=20
> do with types that *don=E2=80=99t* realloc.
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_872_1020773887.1438503612495
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> =E2=80=A6 then what happens? You call <font face=
=3D"Courier">realloc</font> or <font face=3D"Courier">memcpy</font>, right?=
<br></div><div><br></div><div>I store the various types in containers; stan=
dard or otherwise. The containers call <font face=3D"courier new,monospace"=
>realloc</font> or <font face=3D"courier new,monospace">memcpy</font>.</div=
><div><br></div><div><br></div><div>>=C2=A0 It sounds like you want some=
thing like a combination of</div><div>> <font face=3D"Courier">is_trivia=
lly_move_<wbr>constructible</font>=C2=A0and a</div><div>> custom <font f=
ace=3D"Courier">contains_self_references</font> trait.</div><div><br></div>=
<div>What I want is the <font face=3D"courier new,monospace">is_trivially_d=
estructive_movable</font> trait -=C2=A0by=C2=A0whichever of its names (<fon=
t face=3D"courier new,monospace">is_relocatable</font>, <font face=3D"couri=
er new,monospace">is_location_agnostic</font>).</div><div><br></div><div>As=
far as I can see, they are all the same trait.</div><div><br></div><div>Th=
is is on topic for this thread, because your proposal attempts to fill this=
niche in a fairly horrendous way, which would prevent the definition of a =
proper trait with compiler support for inferring it.</div><div><br><br>On S=
unday, August 2, 2015 at 1:52:33 AM UTC-6, David Krauss wrote:</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left=
: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; borde=
r-left-style: solid;"><div style=3D"-ms-word-wrap: break-word;"><br><div><b=
lockquote type=3D"cite"><div>On 2015=E2=80=9308=E2=80=9302, at 3:28 PM, den=
is bider <<a onmousedown=3D"this.href=3D'javascript:';return tru=
e;" onclick=3D"this.href=3D'javascript:';return true;" href=3D"java=
script:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"WkwxgG=
ozDwAJ">isocp...@denisbider.com</a>> wrote:</div><br><div><div style=3D"=
font: 12px/normal Helvetica; text-transform: none; text-indent: 0px; letter=
-spacing: normal; word-spacing: 0px; white-space: normal; font-size-adjust:=
none; font-stretch: normal;" dir=3D"ltr"><div>> The programmer marks po=
inters as relocatable or (potentially) not,</div><div>> then the compile=
r summarizes those attributes, and the</div><div>> programmer uses the s=
ummary to decide whether</div><div>> or not to call<span>=C2=A0</span><f=
ont face=3D"Courier">realloc</font>? No thanks.</div><div><br></div><div>Wh=
at? I can't imagine how you thought that could be what I meant.</div><d=
iv><br></div><div>This is the feature I need.</div><div><br></div><div>If I=
implement my own basic types that are relocatable or location agnostic, </=
div></div></div></blockquote><div><br></div><div>=E2=80=A6 presumably marki=
ng them as such=E2=80=A6</div><br><blockquote type=3D"cite"><div><div style=
=3D"font: 12px/normal Helvetica; text-transform: none; text-indent: 0px; le=
tter-spacing: normal; word-spacing: 0px; white-space: normal; font-size-adj=
ust: none; font-stretch: normal;" dir=3D"ltr"><div>I need the compiler to i=
nfer that my other types, which:</div><div></div></div></div></blockquote><=
div><br></div><div>=E2=80=A6 summarizing the attributes=E2=80=A6</div><br><=
blockquote type=3D"cite"><div><div style=3D"font: 12px/normal Helvetica; te=
xt-transform: none; text-indent: 0px; letter-spacing: normal; word-spacing:=
0px; white-space: normal; font-size-adjust: none; font-stretch: normal;" d=
ir=3D"ltr"><div>- derive from or aggregate my basic types,=C2=A0and</div><d=
iv><br></div><div>- have an implicit or defaulted copy constructor,</div><d=
iv><br></div><div>are also relocatable (or location agnostic).</div><div><b=
r></div><div>That's the feature I need.</div><div></div></div></div></b=
lockquote><div><br></div><div>=E2=80=A6 then what happens? You call <font f=
ace=3D"Courier">realloc</font> or <font face=3D"Courier">memcpy</font>, rig=
ht?</div><br><blockquote type=3D"cite"><div><div style=3D"font: 12px/normal=
Helvetica; text-transform: none; text-indent: 0px; letter-spacing: normal;=
word-spacing: 0px; white-space: normal; font-size-adjust: none; font-stret=
ch: normal;" dir=3D"ltr"><div>I really don't give a rat's rear end =
if this feature is not made available. If I cannot count on the compiler=
9;s support, then any other "support" for this means nothing to m=
e. Zero.</div></div></div></blockquote></div><br><div>I think this discussi=
on is off topic for this thread. It sounds like you want something like a c=
ombination of=C2=A0<font face=3D"Courier">is_trivially_move_<wbr>constructi=
ble</font>=C2=A0and a custom <font face=3D"Courier">contains_self_reference=
s</font> trait. It=E2=80=99s not clear what you want to do with types that =
<i>don=E2=80=99t</i>=C2=A0<font face=3D"Courier">realloc</font>.</div><div>=
<br></div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_872_1020773887.1438503612495--
------=_Part_871_2049778846.1438503612495--
.
Author: Bo Persson <bop@gmb.dk>
Date: Sun, 2 Aug 2015 10:30:12 +0200
Raw View
On 2015-08-02 08:19, David Krauss wrote:
>
>> On 2015=E2=80=9308=E2=80=9302, at 1:05 PM, denis bider <isocppgroup@deni=
sbider.com
>> <mailto:isocppgroup@denisbider.com>> wrote:
>>
>> The problem I see with this is that although it could be "like"
>> memcpy, it is not in fact memcpy.
>
> If you have a trivially movable base subobject B, and no other bytes in
> the object, then this constructor does a memcpy and nothing else:
>
> D::D( B && b ) : B{ std::move( b ) } {}
>
> If you call this constructor in a loop, then nothing is stopping the
> compiler from detecting that it=E2=80=99s nothing but a sequence of memcp=
y
> calls, and merging them into one big memcpy. (I=E2=80=99m not checking, r=
ight
> now, whether such optimizations are actually done. It would be
> surprising if it were implemented by all C++ compilers, or none.)
>
> Note, the compiler can use memcpy even in cases where nothing is
> officially trivial at all. It can do anything that behaves correctly in
> the end.
>
And in cases where the object is properly aligned and an even number of=20
registers in size, the compiler can even do BETTER than a call to memcpy.
Here is my favorite example (by myself :-) of a std::string copy=20
construcor optimized down to 4 machine instructions:
http://stackoverflow.com/a/11639305/597607
This in reply to a question about implementing swap with memcpy...
http://stackoverflow.com/questions/11638271/examples-of-when-a-bitwise-swap=
-is-a-bad-idea
Bo Persson
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 2 Aug 2015 16:32:52 +0800
Raw View
--Apple-Mail=_A0B2B07D-EBC7-45B5-8E62-90EF9C54FBB1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9302, at 4:20 PM, denis bider <isocppgroup@denis=
bider.com> wrote:
>=20
> This is on topic for this thread, because your proposal attempts to fill =
this niche in a fairly horrendous way, which would prevent the definition o=
f a proper trait with compiler support for inferring it.
The binary is_trivially_destructive_movable_v would be approximated well en=
ough by is_trivially_movable_v< destructive_move_base_t< T > > && is_trivia=
lly_destructible_v< destructive_move_base_t< T > >. No language extension n=
eeded.
If an extension discourages people from using realloc to write containers, =
that=E2=80=99s a positive aspect in my book.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_A0B2B07D-EBC7-45B5-8E62-90EF9C54FBB1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=
=E2=80=9302, at 4:20 PM, denis bider <<a href=3D"mailto:isocppgroup@deni=
sbider.com" class=3D"">isocppgroup@denisbider.com</a>> wrote:</div><br c=
lass=3D"Apple-interchange-newline"><div class=3D""><div style=3D"font-famil=
y: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; fo=
nt-weight: normal; letter-spacing: normal; line-height: normal; orphans: au=
to; text-align: start; text-indent: 0px; text-transform: none; white-space:=
normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" =
class=3D"">This is on topic for this thread, because your proposal attempts=
to fill this niche in a fairly horrendous way, which would prevent the def=
inition of a proper trait with compiler support for inferring it.</div></di=
v></blockquote></div><br class=3D""><div class=3D"">The binary <font face=
=3D"Courier" class=3D"">is_trivially_destructive_movable_v</font> woul=
d be approximated well enough by <font face=3D"Courier" class=3D"">is_trivi=
ally_movable_v< destructive_move_base_t< T > > &&&=
nbsp;</font><span style=3D"font-family: Courier;" class=3D"">is_trivially_d=
estructible_v< destructive_move_base_t< T > ></span>. No l=
anguage extension needed.</div><div class=3D""><br class=3D""></div><div cl=
ass=3D"">If an extension discourages people from using <font face=3D"Courie=
r" class=3D"">realloc</font> to write containers, that=E2=80=99s a positive=
aspect in my book.</div><div class=3D""><br class=3D""></div></body></html=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_A0B2B07D-EBC7-45B5-8E62-90EF9C54FBB1--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 2 Aug 2015 16:40:31 +0800
Raw View
--Apple-Mail=_C9620B2E-A264-4815-B2A6-508BD63901D9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
>> On 2015=E2=80=9308=E2=80=9302, at 4:20 PM, denis bider <isocppgroup@deni=
sbider.com <mailto:isocppgroup@denisbider.com>> wrote:
>>=20
>> This is on topic for this thread, because your proposal attempts to fill=
this niche in a fairly horrendous way, which would prevent the definition =
of a proper trait with compiler support for inferring it.
>=20
> The binary is_trivially_destructive_movable_v would be approximated well =
enough by is_trivially_movable_v< destructive_move_base_t< T > > && is_triv=
ially_destructible_v< destructive_move_base_t< T > >. No language extension=
needed.
=E2=80=A6 by the way, the committee and compiler authors have better things=
to do than define =E2=80=9Cproper=E2=80=9D builtin traits for such narrow =
use cases. Pinning all your hopes on highly-specific core language extensio=
ns will likely result in getting nothing.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_C9620B2E-A264-4815-B2A6-508BD63901D9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"><meta http-equiv=3D"Content-Type" content=3D"text/html charset=3D=
utf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: spac=
e; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><div c=
lass=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div class=
=3D"" style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-lin=
e-break: after-white-space;"><div class=3D""><blockquote type=3D"cite" clas=
s=3D"" style=3D"font-family: Helvetica; font-size: 12px; font-style: normal=
; font-variant: normal; font-weight: normal; letter-spacing: normal; line-h=
eight: normal; orphans: auto; text-align: start; text-indent: 0px; text-tra=
nsform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit=
-text-stroke-width: 0px;"><div class=3D"">On 2015=E2=80=9308=E2=80=9302, at=
4:20 PM, denis bider <<a href=3D"mailto:isocppgroup@denisbider.com" cla=
ss=3D"">isocppgroup@denisbider.com</a>> wrote:</div><br class=3D"Apple-i=
nterchange-newline"><div class=3D""><div class=3D"" style=3D"font-family: H=
elvetica; font-size: 12px; font-style: normal; font-variant: normal; font-w=
eight: normal; letter-spacing: normal; line-height: normal; orphans: auto; =
text-align: start; text-indent: 0px; text-transform: none; white-space: nor=
mal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">This=
is on topic for this thread, because your proposal attempts to fill this n=
iche in a fairly horrendous way, which would prevent the definition of a pr=
oper trait with compiler support for inferring it.</div></div></blockquote>=
</div><br class=3D""><div class=3D"">The binary<span class=3D"Apple-convert=
ed-space"> </span><font face=3D"Courier" class=3D"">is_trivially_destr=
uctive_movable_v</font> would be approximated well enough by<span clas=
s=3D"Apple-converted-space"> </span><font face=3D"Courier" class=3D"">=
is_trivially_movable_v< destructive_move_base_t< T > > &am=
p;& </font><span class=3D"" style=3D"font-family: Courier;">is_tri=
vially_destructible_v< destructive_move_base_t< T > ></spa=
n>. No language extension needed.</div></div></div></blockquote></div><br c=
lass=3D""><div class=3D"">=E2=80=A6 by the way, the committee and compiler =
authors have better things to do than define =E2=80=9Cproper=E2=80=9D built=
in traits for such narrow use cases. Pinning all your hopes on highly-speci=
fic core language extensions will likely result in getting nothing.</div><d=
iv class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_C9620B2E-A264-4815-B2A6-508BD63901D9--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 2 Aug 2015 03:01:24 -0700 (PDT)
Raw View
------=_Part_884_1968514485.1438509685056
Content-Type: multipart/alternative;
boundary="----=_Part_885_1493319675.1438509685057"
------=_Part_885_1493319675.1438509685057
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> If an extension discourages people from using realloc to
> write containers, that=E2=80=99s a positive aspect in my book.
Why?
On Sunday, August 2, 2015 at 2:33:02 AM UTC-6, David Krauss wrote:
>
> On 2015=E2=80=9308=E2=80=9302, at 4:20 PM, denis bider <isocp...@denisbid=
er.com=20
> <javascript:>> wrote:
>
> This is on topic for this thread, because your proposal attempts to fill=
=20
> this niche in a fairly horrendous way, which would prevent the definition=
=20
> of a proper trait with compiler support for inferring it.
>
>
> The binary is_trivially_destructive_movable_v would be approximated well=
=20
> enough by is_trivially_movable_v< destructive_move_base_t< T > > && is_tr=
ivially_destructible_v< destructive_move_base_t<=20
> T > >. No language extension needed.
>
> If an extension discourages people from using realloc to write=20
> containers, that=E2=80=99s a positive aspect in my book.
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_885_1493319675.1438509685057
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> If an extension discourages people from using <f=
ont face=3D"Courier">realloc</font> to</div><div>> write containers, tha=
t=E2=80=99s a positive aspect in my book.</div><div><br></div><div>Why?</di=
v><div><br><br>On Sunday, August 2, 2015 at 2:33:02 AM UTC-6, David Krauss =
wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px =
0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-lef=
t-width: 1px; border-left-style: solid;"><div style=3D"-ms-word-wrap: break=
-word;"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9308=E2=80=93=
02, at 4:20 PM, denis bider <<a onmousedown=3D"this.href=3D'javascri=
pt:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscat=
ed-mailto=3D"0HqBEKA1DwAJ">isocp...@denisbider.com</a>> wrote:</div><br>=
<div><div style=3D"font: 12px/normal Helvetica; text-transform: none; text-=
indent: 0px; letter-spacing: normal; word-spacing: 0px; white-space: normal=
; font-size-adjust: none; font-stretch: normal;">This is on topic for this =
thread, because your proposal attempts to fill this niche in a fairly horre=
ndous way, which would prevent the definition of a proper trait with compil=
er support for inferring it.</div></div></blockquote></div><br><div>The bin=
ary <font face=3D"Courier">is_trivially_destructive_<wbr>movable_v</font>=
=C2=A0would be approximated well enough by <font face=3D"Courier">is_trivia=
lly_movable_v<=C2=A0<wbr>destructive_move_base_t< T > > &&a=
mp;=C2=A0</font><span style=3D"font-family: Courier;">is_trivially_destruct=
ible_<wbr>v<=C2=A0destructive_move_base_t< T > ></span>. No lan=
guage extension needed.</div><div><br></div><div>If an extension discourage=
s people from using <font face=3D"Courier">realloc</font> to write containe=
rs, that=E2=80=99s a positive aspect in my book.</div><div><br></div></div>=
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_885_1493319675.1438509685057--
------=_Part_884_1968514485.1438509685056--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 2 Aug 2015 03:16:56 -0700 (PDT)
Raw View
------=_Part_857_2089081243.1438510617033
Content-Type: multipart/alternative;
boundary="----=_Part_858_529351997.1438510617033"
------=_Part_858_529351997.1438510617033
Content-Type: text/plain; charset=UTF-8
> For that, we need something that may have non-zero false
> negatives, but it cannot have any false positive, for any
> reason. Can you guarantee that the compiler would
> never think a type is relocatable when it really isn't?
Yes, I believe so.
We already have rules as to when a move constructor is implicitly declared
or defined.
When a move constructor is implicitly declared, mark the type relocatable
iff:
- the implicitly declared move constructor is non-deleted;
- all non-static data members and direct bases are relocatable.
If the rules for implicit declaration of a move constructor are sound, then
this is also.
On Sunday, August 2, 2015 at 12:22:57 AM UTC-6, Thiago Macieira wrote:
> On Saturday 01 August 2015 22:05:43 denis bider wrote:
> > As far as I can tell, this prevents use of realloc.
> >
> > Arguably, though, we could propose a new function, try_realloc, which
> would
> > fail and not change or move anything, if it fails to enlarge memory in
> > place.
> >
> > A function like try_realloc would benefit all containers, including
> those -
> > and especially those - that must perform deep copy on reallocation.
>
> Right, we need that function anyway, but it's not completely enough.
>
> A realloc() function that manipulated memory mappings could keep an
> existing
> page of allocation and simply remap it elsewhere to enlarge, with no copy
> required. try_realloc + copy can't do zero copies.
>
> > Possibly, then - this + try_realloc could get the job sort of done.
> >
> > But I have another problem with this - which is that it seems to
> > prevent, or make harder, introduction of the feature I *really* want.
> What
> > I *really* want is a standardized rule that would allow the developer to
> > rely on the compiler to automatically mark types is_location_agnostic or
> > is_relocatable. In my opinion, the compiler should do the deduction, and
> > the developer should check the result. This way, the compiler and the
> > developer make each other stronger.
>
> For that, we need something that may have non-zero false negatives, but it
> cannot have any false positive, for any reason. Can you guarantee that the
> compiler would never think a type is relocatable when it really isn't?
>
> > To me, this is *the* core feature for which I want language support. If
> I
> > can't rely on the compiler to help me correctly mark my types, then to
> me,
> > there isn't a major difference to having a standardized property, as
> > opposed to rolling my own. In either case, I won't use it, because it's
> too
> > dangerous. I don't trust myself to not introduce errors if I'm required
> > to manually mark every type.
>
> For me, it isn't. The core feature for me is the ability to memcpy or
> realloc
> confidently. But it's an optimisation, so if I miss a type or two, the
> worst
> case scanerio is that it's slightly slower than it could have been.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_858_529351997.1438510617033
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><p>> For that, we need something that may have non-zero=
false<br>> negatives, but it cannot have any false positive, for any<br=
>> reason. Can you guarantee that the compiler would<br>> never think=
a type is relocatable when it really isn't? </p><div><br></div><div>Ye=
s, I believe so.</div><div><br></div><div>We already have rules as to when =
a move constructor is implicitly declared or defined.</div><div><br></div><=
div>When a move constructor is implicitly declared, mark the type relocatab=
le iff:</div><div><br></div><div>- the implicitly declared move constructor=
is non-deleted;</div><div><br></div><div>- all non-static data members and=
direct bases are relocatable.</div><div><br></div><div>If the rules for im=
plicit declaration of a move constructor are sound, then this is also.<br><=
br><br>On Sunday, August 2, 2015 at 12:22:57 AM UTC-6, Thiago Macieira wrot=
e:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8e=
x; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wi=
dth: 1px; border-left-style: solid;">On Saturday 01 August 2015 22:05:43 de=
nis bider wrote:
<br>> As far as I can tell, this prevents use of realloc.
<br>>=20
<br>> Arguably, though, we could propose a new function, try_realloc, wh=
ich would
<br>> fail and not change or move anything, if it fails to enlarge memor=
y in
<br>> place.
<br>>=20
<br>> A function like try_realloc would benefit all containers, includin=
g those -
<br>> and especially those - that must perform deep copy on reallocation=
..
<br>
<br>Right, we need that function anyway, but it's not completely enough=
..
<br>
<br>A realloc() function that manipulated memory mappings could keep an exi=
sting=20
<br>page of allocation and simply remap it elsewhere to enlarge, with no co=
py=20
<br>required. try_realloc + copy can't do zero copies.
<br>
<br>> Possibly, then - this + try_realloc could get the job sort of done=
..
<br>>=20
<br>> But I have another problem with this - which is that it seems to
<br>> prevent, or make harder, introduction of the feature I *really* wa=
nt. What
<br>> I *really* want is a standardized rule that would allow the develo=
per to
<br>> rely on the compiler to automatically mark types is_location_agnos=
tic or
<br>> is_relocatable. In my opinion, the compiler should do the deductio=
n, and
<br>> the developer should check the result. This way, the compiler and =
the
<br>> developer make each other stronger.
<br>
<br>For that, we need something that may have non-zero false negatives, but=
it=20
<br>cannot have any false positive, for any reason. Can you guarantee that =
the=20
<br>compiler would never think a type is relocatable when it really isn'=
;t?
<br>
<br>> To me, this is *the* core feature for which I want language suppor=
t. If I
<br>> can't rely on the compiler to help me correctly mark my types,=
then to me,
<br>> there isn't a major difference to having a standardized proper=
ty, as
<br>> opposed to rolling my own. In either case, I won't use it, bec=
ause it's too
<br>> dangerous. I don't trust myself to not introduce errors if I&#=
39;m required
<br>> to manually mark every type.
<br>
<br>For me, it isn't. The core feature for me is the ability to memcpy =
or realloc=20
<br>confidently. But it's an optimisation, so if I miss a type or two, =
the worst=20
<br>case scanerio is that it's slightly slower than it could have been.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_858_529351997.1438510617033--
------=_Part_857_2089081243.1438510617033--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 2 Aug 2015 03:44:46 -0700 (PDT)
Raw View
------=_Part_952_1904346407.1438512286865
Content-Type: multipart/alternative;
boundary="----=_Part_953_135728980.1438512286865"
------=_Part_953_135728980.1438512286865
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
In practical observation on x64 Windows, memcpy is 2 - 9 times faster than=
=20
a loop of placement new followed by destructor.
Tested VS 2015 and GCC 4.9.2.
The greatest speedup - factor of 5-9 - is with commonly used container=20
sizes of 100 - 1000 objects.
> nothing is stopping the compiler from detecting that
> it=E2=80=99s nothing but a sequence of memcpy calls
Nothing is stopping the compiler, except for that it isn't yet a fully=20
evolved AI, and relies on humans to craft optimization rules that fail=20
about as often as they succeed, subject to quirky conditions; and the=20
developer has no way of knowing which is going to happen in advance.
One of the main advantages of C++ is that it does *not* separate the=20
developer from the platform, and does not require trusting complex=20
infrastructure to either optimize code, or fail to.=20
On Sunday, August 2, 2015 at 2:30:24 AM UTC-6, Bo Persson wrote:
> On 2015-08-02 08:19, David Krauss wrote:=20
> >=20
> >> On 2015=E2=80=9308=E2=80=9302, at 1:05 PM, denis bider <isocp...@denis=
bider.com=20
> <javascript:>=20
> >> <mailto:isocp...@denisbider.com <javascript:>>> wrote:=20
> >>=20
> >> The problem I see with this is that although it could be "like"=20
> >> memcpy, it is not in fact memcpy.=20
> >=20
> > If you have a trivially movable base subobject B, and no other bytes in=
=20
> > the object, then this constructor does a memcpy and nothing else:=20
> >=20
> > D::D( B && b ) : B{ std::move( b ) } {}=20
> >=20
> > If you call this constructor in a loop, then nothing is stopping the=20
> > compiler from detecting that it=E2=80=99s nothing but a sequence of mem=
cpy=20
> > calls, and merging them into one big memcpy. (I=E2=80=99m not checking,=
right=20
> > now, whether such optimizations are actually done. It would be=20
> > surprising if it were implemented by all C++ compilers, or none.)=20
> >=20
> > Note, the compiler can use memcpy even in cases where nothing is=20
> > officially trivial at all. It can do anything that behaves correctly in=
=20
> > the end.=20
> >=20
>
> And in cases where the object is properly aligned and an even number of=
=20
> registers in size, the compiler can even do BETTER than a call to memcpy.=
=20
>
> Here is my favorite example (by myself :-) of a std::string copy=20
> construcor optimized down to 4 machine instructions:=20
>
> http://stackoverflow.com/a/11639305/597607=20
>
>
> This in reply to a question about implementing swap with memcpy...=20
>
>
> http://stackoverflow.com/questions/11638271/examples-of-when-a-bitwise-sw=
ap-is-a-bad-idea=20
>
>
> Bo Persson=20
>
>
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_953_135728980.1438512286865
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>In practical observation on x64 Windows,=C2=A0memcpy =
is 2 - 9 times faster than a loop of placement new followed by destructor.<=
/div><div><br></div><div>Tested VS 2015 and GCC 4.9.2.</div><div><br></div>=
<div>The greatest speedup - factor of 5-9 -=C2=A0is with commonly used cont=
ainer sizes of 100 - 1000 objects.</div><div><br></div><div><br></div><div>=
>=C2=A0 nothing is stopping the compiler from detecting that</div><div>&=
gt; it=E2=80=99s nothing but a sequence of <font face=3D"Courier">memcpy</f=
ont> calls</div><div><br></div><div>Nothing is stopping the compiler, excep=
t for that it isn't yet a fully evolved AI, and relies on humans to cra=
ft optimization rules that fail about as often as they succeed, subject to =
quirky conditions;=C2=A0and=C2=A0the developer has no way of knowing which =
is going to happen in advance.</div><div><br></div><div>One of the main=C2=
=A0advantages=C2=A0of=C2=A0C++=C2=A0is that it does <em>not</em> separate t=
he developer=C2=A0from the platform, and does not require trusting complex =
infrastructure to either optimize code, or fail to. </div><div><br><br>On S=
unday, August 2, 2015 at 2:30:24 AM UTC-6, Bo Persson wrote:</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: =
1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-=
left-style: solid;">On 2015-08-02 08:19, David Krauss wrote:
<br>>
<br>>> On 2015=E2=80=9308=E2=80=9302, at 1:05 PM, denis bider <<a =
onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"t=
his.href=3D'javascript:';return true;" href=3D"javascript:" target=
=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"BGU6T3s1DwAJ">isocp..=
..@denisbider.com</a>
<br>>> <mailto:<a onmousedown=3D"this.href=3D'javascript:'=
;return true;" onclick=3D"this.href=3D'javascript:';return true;" h=
ref=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailt=
o=3D"BGU6T3s1DwAJ">isocp...@<wbr>denisbider.com</a>>> wrote:
<br>>>
<br>>> The problem I see with this is that although it could be "=
;like"
<br>>> memcpy, it is not in fact memcpy.
<br>>
<br>> If you have a trivially movable base subobject B, and no other byt=
es in
<br>> the object, then this constructor does a memcpy and nothing else:
<br>>
<br>> D::D( B && b ) : B{ std::move( b ) } {}
<br>>
<br>> If you call this constructor in a loop, then nothing is stopping t=
he
<br>> compiler from detecting that it=E2=80=99s nothing but a sequence o=
f memcpy
<br>> calls, and merging them into one big memcpy. (I=E2=80=99m not chec=
king, right
<br>> now, whether such optimizations are actually done. It would be
<br>> surprising if it were implemented by all C++ compilers, or none.)
<br>>
<br>> Note, the compiler can use memcpy even in cases where nothing is
<br>> officially trivial at all. It can do anything that behaves correct=
ly in
<br>> the end.
<br>>
<br>
<br>And in cases where the object is properly aligned and an even number of=
=20
<br>registers in size, the compiler can even do BETTER than a call to memcp=
y.
<br>
<br>Here is my favorite example (by myself :-) of a std::string copy=20
<br>construcor optimized down to 4 machine instructions:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fstackoverflow.com%2Fa%2F11639305%2F597607\46sa\75D\46sntz\0751\46usg=
\75AFQjCNFU1MXVpXAahmCO902OY9hMBksrDA';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fa%=
2F11639305%2F597607\46sa\75D\46sntz\0751\46usg\75AFQjCNFU1MXVpXAahmCO902OY9=
hMBksrDA';return true;" href=3D"http://stackoverflow.com/a/11639305/597=
607" target=3D"_blank" rel=3D"nofollow">http://stackoverflow.com/a/<wbr>116=
39305/597607</a>
<br>
<br>
<br>This in reply to a question about implementing swap with memcpy...
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fstackoverflow.com%2Fquestions%2F11638271%2Fexamples-of-when-a-bitwis=
e-swap-is-a-bad-idea\46sa\75D\46sntz\0751\46usg\75AFQjCNH-hvRKpo_yvpbgZjx_t=
Pq8AQfhLw';return true;" onclick=3D"this.href=3D'http://www.google.=
com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F11638271%2Fexample=
s-of-when-a-bitwise-swap-is-a-bad-idea\46sa\75D\46sntz\0751\46usg\75AFQjCNH=
-hvRKpo_yvpbgZjx_tPq8AQfhLw';return true;" href=3D"http://stackoverflow=
..com/questions/11638271/examples-of-when-a-bitwise-swap-is-a-bad-idea" targ=
et=3D"_blank" rel=3D"nofollow">http://stackoverflow.com/<wbr>questions/1163=
8271/examples-<wbr>of-when-a-bitwise-swap-is-a-<wbr>bad-idea</a>
<br>
<br>
<br>Bo Persson
<br>
<br>
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_953_135728980.1438512286865--
------=_Part_952_1904346407.1438512286865--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 2 Aug 2015 20:11:51 +0800
Raw View
--Apple-Mail=_F1A78B4C-C556-4EB7-B976-FDFDA75A64D3
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9302, at 6:44 PM, denis bider <isocppgroup@denis=
bider.com> wrote:
>=20
> In practical observation on x64 Windows, memcpy is 2 - 9 times faster tha=
n a loop of placement new followed by destructor.
=E2=80=9CPlacement new=E2=80=9D means calling a constructor. Yes, it=E2=80=
=99s possible to write a benchmark with constructors which goes faster when=
they=E2=80=99re not called. That doesn=E2=80=99t make the optimization val=
id.
> The greatest speedup - factor of 5-9 - is with commonly used container si=
zes of 100 - 1000 objects.
>=20
>=20
> > nothing is stopping the compiler from detecting that
> > it=E2=80=99s nothing but a sequence of memcpy calls
>=20
> Nothing is stopping the compiler, except for that it isn't yet a fully ev=
olved AI,
Well, Clang at least does a pretty good job: http://goo.gl/x188jS <http://g=
oo.gl/x188jS> (godbolt.org link)
The other compilers there aren=E2=80=99t too shabby either. Can=E2=80=99t s=
peak for MSVC.
> and relies on humans to craft optimization rules that fail about as often=
as they succeed, subject to quirky conditions; and the developer has no wa=
y of knowing which is going to happen in advance.
>=20
> One of the main advantages of C++ is that it does not separate the develo=
per from the platform, and does not require trusting complex infrastructure=
to either optimize code, or fail to.
In that case, my proposal shouldn=E2=80=99t interfere with the motivation f=
or your effort to make a trait that automatically computes whether a class =
is compatible with realloc.
However, it sounds like the language you=E2=80=99re describing is C (with o=
ptimizations disabled), not C++.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_F1A78B4C-C556-4EB7-B976-FDFDA75A64D3
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=
=E2=80=9302, at 6:44 PM, denis bider <<a href=3D"mailto:isocppgroup@deni=
sbider.com" class=3D"">isocppgroup@denisbider.com</a>> wrote:</div><br c=
lass=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=
=3D""><div class=3D"">In practical observation on x64 Windows, memcpy =
is 2 - 9 times faster than a loop of placement new followed by destructor.<=
/div></div></div></blockquote><div><br class=3D""></div><div>=E2=80=9CPlace=
ment new=E2=80=9D means calling a constructor. Yes, it=E2=80=99s possible t=
o write a benchmark with constructors which goes faster when they=E2=80=99r=
e not called. That doesn=E2=80=99t make the optimization valid.</div><br cl=
ass=3D""><blockquote type=3D"cite" class=3D""><div dir=3D"ltr" class=3D""><=
div class=3D"">The greatest speedup - factor of 5-9 - is with commonly=
used container sizes of 100 - 1000 objects.</div><div class=3D""><br class=
=3D""></div><div class=3D""><br class=3D""></div><div class=3D"">> =
nothing is stopping the compiler from detecting that</div><div class=3D"">=
> it=E2=80=99s nothing but a sequence of <font face=3D"Courier" class=3D=
"">memcpy</font> calls</div><div class=3D""><br class=3D""></div><div class=
=3D"">Nothing is stopping the compiler, except for that it isn't yet a full=
y evolved AI, </div></div></blockquote><div><br class=3D""></div><div>Well,=
Clang at least does a pretty good job: <a href=3D"http://goo.gl/x188j=
S" class=3D"">http://goo.gl/x188jS</a> (<a href=3D"http://godbolt.org"=
class=3D"">godbolt.org</a> link)</div><div><br class=3D""></div><div>The o=
ther compilers there aren=E2=80=99t too shabby either. Can=E2=80=99t speak =
for MSVC.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div dir=
=3D"ltr" class=3D""><div class=3D"">and relies on humans to craft optimizat=
ion rules that fail about as often as they succeed, subject to quirky condi=
tions; and the developer has no way of knowing which is going to =
happen in advance.</div><div class=3D""><br class=3D""></div><div class=3D"=
">One of the main advantages of C++ is that it does <em=
class=3D"">not</em> separate the developer from the platform, and doe=
s not require trusting complex infrastructure to either optimize code, or f=
ail to. </div></div></blockquote><div><br class=3D""></div><div>In that cas=
e, my proposal shouldn=E2=80=99t interfere with the motivation for your eff=
ort to make a trait that automatically computes whether a class is compatib=
le with <font face=3D"Courier" class=3D"">realloc</font>.</div><div><br cla=
ss=3D""></div><div>However, it sounds like the language you=E2=80=99re desc=
ribing is C (with optimizations disabled), not C++.</div><div><br class=3D"=
"></div></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_F1A78B4C-C556-4EB7-B976-FDFDA75A64D3--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 02 Aug 2015 10:18:34 -0700
Raw View
On Sunday 02 August 2015 14:19:02 David Krauss wrote:
> If you have a trivially movable base subobject B, and no other bytes in t=
he
> object, then this constructor does a memcpy and nothing else:
>=20
> D::D( B && b ) : B{ std::move( b ) } {}
>=20
> If you call this constructor in a loop, then nothing is stopping the
> compiler from detecting that it=E2=80=99s nothing but a sequence of memcp=
y calls,
> and merging them into one big memcpy. (I=E2=80=99m not checking, right no=
w, whether
> such optimizations are actually done. It would be surprising if it were
> implemented by all C++ compilers, or none.)
Why should this optimisation apply only to classes with inline constructors=
?=20
Absolutely none of the compilers will optimise the following B base class:
B.h:
struct B=20
{
B(const B &);=20
B(B &&);=20
int i,j,k,l;
};
B.cpp:
B::B(const B &) =3D default;=20
B::B(B &&) =3D default;
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 2 Aug 2015 11:58:20 -0700 (PDT)
Raw View
------=_Part_1173_304098463.1438541900595
Content-Type: multipart/alternative;
boundary="----=_Part_1174_1284991292.1438541900595"
------=_Part_1174_1284991292.1438541900595
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> =E2=80=9CPlacement new=E2=80=9D means calling a constructor.
I meant placement new that calls a move constructor.
However, you are correct: the benchmark I was referring to was calling=20
standard, non-sliced std::string move constructor and destructor.
I tested right now instead on a POD class of similar size (24 bytes, 3 long=
=20
long members), with a move constructor that just copies the members, and no=
=20
destructor - mimicking your slicing proposal.
You are correct that performance in this circumstance reaches reasonable=20
levels. At worst, memcpy is better by a factor of 2.
I therefore withdraw this part of my complaint.
But:
> Yes, it=E2=80=99s possible to write a benchmark with
> constructors which goes faster when
> they=E2=80=99re not called. That doesn=E2=80=99t make
> the optimization valid.
This leaves the problem that your proposal is indescribably ugly.
What you're doing is forcing *all* objects that want to implement=20
relocation to split their data members into a base away from the code, and=
=20
then to nominate that base for destructive moving.
You are doing this to shoehorn support for relocation, while preserving a=
=20
conceptual language deficiency in place. You're doing this to work around=
=20
the status quo, but while you do so, you don't even benefit from not having=
=20
to change the language. You're *still* having to change the language, in=20
order to allow slicing to work in the first place.
You are doing all of this, for the sole and only purpose of having this:
template <typename T, typename B =3D
typename destructive_move_base_t<B> >
T* holy_blessed_relocate(void* d, T* s, size_t n) {
T* dt { (T*) d };
for (size_t i=3D0; i!=3Dn; ++i) {
new (dt+i) T(std::move(s[i]));
s[i].~T();
}
return dt;}
instead of this:
template <typename T, enable_if_t<is_relocatable_v<T>, int>=3D0>
T* holy_blessed_relocate(void* d, T* s, size_t n)
{ memcpy(d, s, n*sizeof(T)); return (T*) d; }
template <typename T, enable_if_t<!is_relocatable_v<T>, int>=3D0>
T* holy_blessed_relocate(void* d, T* s, size_t n) {
T* dt { (T*) d };
for (size_t i=3D0; i!=3Dn; ++i) {
new (dt+i) T(std::move(s[i]));
s[i].~T();
}
return dt;}
These lines of code is the whole difference your slicing approach boils=20
down to.
In exchange for this, you are asking *everyone in the world* to pay for=20
your "conceptual beauty" - such as it is - by forcing them to separate=20
their relocatable implementations into two separate objects.
This is a violation of common sense, a humiliation for C++, and proof that=
=20
the language is being run by people out of touch with the world.
Whether we call holy_blessed_relocate<T> implemented one way, or the other=
=20
way, static analysis tools continue to work exactly the same. The *only*=20
difference is a trivial implementation detail. And the cost you're paying=
=20
for this detail is to make all the *rest* of the code ugly.
On Sunday, August 2, 2015 at 6:12:01 AM UTC-6, David Krauss wrote:
>
> On 2015=E2=80=9308=E2=80=9302, at 6:44 PM, denis bider <isocp...@denisbid=
er.com=20
> <javascript:>> wrote:
>
> In practical observation on x64 Windows, memcpy is 2 - 9 times faster tha=
n=20
> a loop of placement new followed by destructor.
>
>
> =E2=80=9CPlacement new=E2=80=9D means calling a constructor. Yes, it=E2=
=80=99s possible to write a=20
> benchmark with constructors which goes faster when they=E2=80=99re not ca=
lled. That=20
> doesn=E2=80=99t make the optimization valid.
>
> The greatest speedup - factor of 5-9 - is with commonly used container=20
> sizes of 100 - 1000 objects.
>
>
> > nothing is stopping the compiler from detecting that
> > it=E2=80=99s nothing but a sequence of memcpy calls
>
> Nothing is stopping the compiler, except for that it isn't yet a fully=20
> evolved AI,=20
>
>
> Well, Clang at least does a pretty good job: http://goo.gl/x188jS (
> godbolt.org link)
>
> The other compilers there aren=E2=80=99t too shabby either. Can=E2=80=99t=
speak for MSVC.
>
> and relies on humans to craft optimization rules that fail about as often=
=20
> as they succeed, subject to quirky conditions; and the developer has no w=
ay=20
> of knowing which is going to happen in advance.
>
> One of the main advantages of C++ is that it does *not* separate the=20
> developer from the platform, and does not require trusting complex=20
> infrastructure to either optimize code, or fail to.=20
>
>
> In that case, my proposal shouldn=E2=80=99t interfere with the motivation=
for your=20
> effort to make a trait that automatically computes whether a class is=20
> compatible with realloc.
>
> However, it sounds like the language you=E2=80=99re describing is C (with=
=20
> optimizations disabled), not C++.
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1174_1284991292.1438541900595
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> =E2=80=9CPlacement new=E2=80=9D means calling a =
constructor.</div><div><br></div><div>I meant placement new that calls a mo=
ve constructor.</div><div><br></div><div>However, you are correct: the benc=
hmark I was referring to was calling standard, non-sliced std::string move =
constructor and destructor.</div><div><br></div><div>I tested right now ins=
tead on a POD class of similar size (24 bytes, 3 long long members), with a=
move constructor that just copies the members, and no destructor - mimicki=
ng your slicing proposal.</div><div><br></div><div>You are correct that per=
formance in this circumstance=C2=A0reaches reasonable levels.=C2=A0At worst=
, memcpy is better by a factor of 2.</div><div><br></div><div>I therefore w=
ithdraw this part of my complaint.</div><div><br></div><div>But:</div><div>=
<br></div><div><br></div><div><div>> Yes, it=E2=80=99s possible to write=
a benchmark with</div><div>> constructors which goes faster when</div><=
div>> they=E2=80=99re not called. That doesn=E2=80=99t make</div><div>&g=
t; the optimization valid.</div></div><div><br></div><div>This leaves the p=
roblem that your proposal is indescribably ugly.</div><div><br></div><div>W=
hat you're doing is forcing <strong>all</strong> objects that want to i=
mplement relocation to split their data members into a base away from the c=
ode, and then to nominate that base for destructive moving.</div><div><br><=
/div><div>You are doing this to shoehorn support for relocation, while=C2=
=A0preserving a conceptual language deficiency in place. You're doing t=
his to work around the status quo, but while you do so, you don't even =
benefit from not having to change the language. You're <em>still</em> h=
aving to change the language, in order to allow slicing to work in the firs=
t place.</div><div><br></div><div>You are doing all of this,=C2=A0for the s=
ole and only purpose of having=C2=A0this:</div><div><br></div><div><br></di=
v><div><pre style=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);"=
><span style=3D"color: rgb(32, 0, 128); font-weight: bold;"><br></span></pr=
e><pre style=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);"><spa=
n style=3D"color: rgb(32, 0, 128); font-weight: bold;">template</span> <spa=
n style=3D"color: rgb(64, 96, 128);"><</span><span style=3D"color: rgb(3=
2, 0, 128); font-weight: bold;">typename</span> T<span style=3D"color: rgb(=
48, 128, 128);">,</span> <span style=3D"color: rgb(32, 0, 128); font-weight=
: bold;">typename</span> B <span style=3D"color: rgb(48, 128, 128);">=3D</s=
pan>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">typename</sp=
an> destructive_move_base_t<span style=3D"color: rgb(64, 96, 128);"><</s=
pan>B<span style=3D"color: rgb(64, 96, 128);">></span> <span style=3D"co=
lor: rgb(64, 96, 128);">></span>
T<span style=3D"color: rgb(48, 128, 128);">*</span> holy_blessed_relocate<s=
pan style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(3=
2, 0, 128); font-weight: bold;">void</span><span style=3D"color: rgb(48, 12=
8, 128);">*</span> d<span style=3D"color: rgb(48, 128, 128);">,</span> T<sp=
an style=3D"color: rgb(48, 128, 128);">*</span> s<span style=3D"color: rgb(=
48, 128, 128);">,</span> <span style=3D"color: rgb(0, 48, 96);">size_t</spa=
n> n<span style=3D"color: rgb(48, 128, 128);">)</span> <span style=3D"color=
: rgb(64, 96, 128);">{</span>
T<span style=3D"color: rgb(48, 128, 128);">*</span> dt <span style=3D"c=
olor: rgb(64, 96, 128);">{</span> <span style=3D"color: rgb(48, 128, 128);"=
>(</span>T<span style=3D"color: rgb(48, 128, 128);">*</span><span style=3D"=
color: rgb(48, 128, 128);">)</span> d <span style=3D"color: rgb(64, 96, 128=
);">}</span><span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">for</span> <=
span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(=
0, 48, 96);">size_t</span> i<span style=3D"color: rgb(48, 128, 128);">=3D</=
span><span style=3D"color: rgb(0, 140, 0);">0</span><span style=3D"color: r=
gb(64, 96, 128);">;</span> i<span style=3D"color: rgb(48, 128, 128);">!</sp=
an><span style=3D"color: rgb(48, 128, 128);">=3D</span>n<span style=3D"colo=
r: rgb(64, 96, 128);">;</span> <span style=3D"color: rgb(48, 128, 128);">+<=
/span><span style=3D"color: rgb(48, 128, 128);">+</span>i<span style=3D"col=
or: rgb(48, 128, 128);">)</span> <span style=3D"color: rgb(64, 96, 128);">{=
</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">new</spa=
n> <span style=3D"color: rgb(48, 128, 128);">(</span>dt<span style=3D"color=
: rgb(48, 128, 128);">+</span>i<span style=3D"color: rgb(48, 128, 128);">)<=
/span> T<span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"co=
lor: rgb(0, 102, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">=
::</span><span style=3D"color: rgb(0, 48, 96);">move</span><span style=3D"c=
olor: rgb(48, 128, 128);">(</span>s<span style=3D"color: rgb(48, 128, 128);=
">[</span>i<span style=3D"color: rgb(48, 128, 128);">]</span><span style=3D=
"color: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(48, 128, 128)=
;">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
s<span style=3D"color: rgb(48, 128, 128);">[</span>i<span style=3D"=
color: rgb(48, 128, 128);">]</span><span style=3D"color: rgb(48, 128, 128);=
">.</span><span style=3D"color: rgb(48, 128, 128);">~</span>T<span style=3D=
"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48, 128, 128)=
;">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(64, 96, 128);">}</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">return</span=
> dt<span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(64, 96, 128);">}</span></pre><pre style=3D"backgr=
ound: rgb(246, 248, 255); color: rgb(0, 0, 32);"><br></pre></div><div><br><=
/div><div><br></div><div>instead of this:</div><div><br></div><div><br></di=
v><div><pre style=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);"=
><span style=3D"color: rgb(32, 0, 128); font-weight: bold;"><br></span></pr=
e><pre style=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);"><spa=
n style=3D"color: rgb(32, 0, 128); font-weight: bold;">template</span> <spa=
n style=3D"color: rgb(64, 96, 128);"><</span><span style=3D"color: rgb(3=
2, 0, 128); font-weight: bold;">typename</span> T<span style=3D"color: rgb(=
48, 128, 128);">,</span> enable_if_t<span style=3D"color: rgb(64, 96, 128);=
"><</span>is_relocatable_v<span style=3D"color: rgb(64, 96, 128);"><<=
/span>T<span style=3D"color: rgb(64, 96, 128);">></span><span style=3D"c=
olor: rgb(48, 128, 128);">,</span> <span style=3D"color: rgb(32, 0, 128); f=
ont-weight: bold;">int</span><span style=3D"color: rgb(64, 96, 128);">><=
/span><span style=3D"color: rgb(48, 128, 128);">=3D</span><span style=3D"co=
lor: rgb(0, 140, 0);">0</span><span style=3D"color: rgb(64, 96, 128);">>=
</span>
T<span style=3D"color: rgb(48, 128, 128);">*</span> holy_blessed_relocate<s=
pan style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(3=
2, 0, 128); font-weight: bold;">void</span><span style=3D"color: rgb(48, 12=
8, 128);">*</span> d<span style=3D"color: rgb(48, 128, 128);">,</span> T<sp=
an style=3D"color: rgb(48, 128, 128);">*</span> s<span style=3D"color: rgb(=
48, 128, 128);">,</span> <span style=3D"color: rgb(0, 48, 96);">size_t</spa=
n> n<span style=3D"color: rgb(48, 128, 128);">)</span>
<span style=3D"color: rgb(64, 96, 128);">{</span> <span style=3D"color:=
rgb(0, 48, 96);">memcpy</span><span style=3D"color: rgb(48, 128, 128);">(<=
/span>d<span style=3D"color: rgb(48, 128, 128);">,</span> s<span style=3D"c=
olor: rgb(48, 128, 128);">,</span> n<span style=3D"color: rgb(48, 128, 128)=
;">*</span><span style=3D"color: rgb(32, 0, 128); font-weight: bold;">sizeo=
f</span><span style=3D"color: rgb(48, 128, 128);">(</span>T<span style=3D"c=
olor: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(48, 128, 128);"=
>)</span><span style=3D"color: rgb(64, 96, 128);">;</span> <span style=3D"c=
olor: rgb(32, 0, 128); font-weight: bold;">return</span> <span style=3D"col=
or: rgb(48, 128, 128);">(</span>T<span style=3D"color: rgb(48, 128, 128);">=
*</span><span style=3D"color: rgb(48, 128, 128);">)</span> d<span style=3D"=
color: rgb(64, 96, 128);">;</span> <span style=3D"color: rgb(64, 96, 128);"=
>}</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">template</span> =
<span style=3D"color: rgb(64, 96, 128);"><</span><span style=3D"color: r=
gb(32, 0, 128); font-weight: bold;">typename</span> T<span style=3D"color: =
rgb(48, 128, 128);">,</span> enable_if_t<span style=3D"color: rgb(48, 128, =
128);"><</span><span style=3D"color: rgb(48, 128, 128);">!</span>is_relo=
catable_v<span style=3D"color: rgb(64, 96, 128);"><</span>T<span style=
=3D"color: rgb(64, 96, 128);">></span><span style=3D"color: rgb(48, 128,=
128);">,</span> <span style=3D"color: rgb(32, 0, 128); font-weight: bold;"=
>int</span><span style=3D"color: rgb(64, 96, 128);">></span><span style=
=3D"color: rgb(48, 128, 128);">=3D</span><span style=3D"color: rgb(0, 140, =
0);">0</span><span style=3D"color: rgb(48, 128, 128);">></span>
T<span style=3D"color: rgb(48, 128, 128);">*</span> holy_blessed_relocate<s=
pan style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(3=
2, 0, 128); font-weight: bold;">void</span><span style=3D"color: rgb(48, 12=
8, 128);">*</span> d<span style=3D"color: rgb(48, 128, 128);">,</span> T<sp=
an style=3D"color: rgb(48, 128, 128);">*</span> s<span style=3D"color: rgb(=
48, 128, 128);">,</span> <span style=3D"color: rgb(0, 48, 96);">size_t</spa=
n> n<span style=3D"color: rgb(48, 128, 128);">)</span> <span style=3D"color=
: rgb(64, 96, 128);">{</span>
T<span style=3D"color: rgb(48, 128, 128);">*</span> dt <span style=3D"c=
olor: rgb(64, 96, 128);">{</span> <span style=3D"color: rgb(48, 128, 128);"=
>(</span>T<span style=3D"color: rgb(48, 128, 128);">*</span><span style=3D"=
color: rgb(48, 128, 128);">)</span> d <span style=3D"color: rgb(64, 96, 128=
);">}</span><span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">for</span> <=
span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(=
0, 48, 96);">size_t</span> i<span style=3D"color: rgb(48, 128, 128);">=3D</=
span><span style=3D"color: rgb(0, 140, 0);">0</span><span style=3D"color: r=
gb(64, 96, 128);">;</span> i<span style=3D"color: rgb(48, 128, 128);">!</sp=
an><span style=3D"color: rgb(48, 128, 128);">=3D</span>n<span style=3D"colo=
r: rgb(64, 96, 128);">;</span> <span style=3D"color: rgb(48, 128, 128);">+<=
/span><span style=3D"color: rgb(48, 128, 128);">+</span>i<span style=3D"col=
or: rgb(48, 128, 128);">)</span> <span style=3D"color: rgb(64, 96, 128);">{=
</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">new</spa=
n> <span style=3D"color: rgb(48, 128, 128);">(</span>dt<span style=3D"color=
: rgb(48, 128, 128);">+</span>i<span style=3D"color: rgb(48, 128, 128);">)<=
/span> T<span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"co=
lor: rgb(0, 102, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">=
::</span><span style=3D"color: rgb(0, 48, 96);">move</span><span style=3D"c=
olor: rgb(48, 128, 128);">(</span>s<span style=3D"color: rgb(48, 128, 128);=
">[</span>i<span style=3D"color: rgb(48, 128, 128);">]</span><span style=3D=
"color: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(48, 128, 128)=
;">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
s<span style=3D"color: rgb(48, 128, 128);">[</span>i<span style=3D"=
color: rgb(48, 128, 128);">]</span><span style=3D"color: rgb(48, 128, 128);=
">.</span><span style=3D"color: rgb(48, 128, 128);">~</span>T<span style=3D=
"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48, 128, 128)=
;">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(64, 96, 128);">}</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">return</span=
> dt<span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(64, 96, 128);">}</span></pre><pre style=3D"backgr=
ound: rgb(246, 248, 255); color: rgb(0, 0, 32);"><span style=3D"color: rgb(=
64, 96, 128);"></span>
</pre></div><div><br></div><div><br></div><div>These lines of code is=C2=A0=
the whole difference your=C2=A0slicing approach boils down to.</div><div><b=
r></div><div>In exchange for this, you are asking <em>everyone in the world=
</em> to pay for your "conceptual beauty" -=C2=A0such as it is - =
by forcing them to separate their relocatable implementations into two sepa=
rate objects.</div><div><br></div><div>This is a violation of common sense,=
a humiliation=C2=A0for C++, and proof that the language is being run by pe=
ople out of touch with the world.</div><div><br></div><div>Whether we call =
<font face=3D"courier new,monospace">holy_blessed_relocate<T></font> =
implemented one way, or the other way, static analysis tools continue to wo=
rk exactly the same. The <em>only</em> difference is a trivial implementati=
on detail. And the cost you're paying for=C2=A0this=C2=A0detail=C2=A0is=
to make all the <em>rest</em> of the code ugly.</div><div><br><br>On Sunda=
y, August 2, 2015 at 6:12:01 AM UTC-6, David Krauss wrote:</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1e=
x; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-le=
ft-style: solid;"><div style=3D"-ms-word-wrap: break-word;"><br><div><block=
quote type=3D"cite"><div>On 2015=E2=80=9308=E2=80=9302, at 6:44 PM, denis b=
ider <<a onmousedown=3D"this.href=3D'javascript:';return true;" =
onclick=3D"this.href=3D'javascript:';return true;" href=3D"javascri=
pt:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"lOMfJ5NBDw=
AJ">isocp...@denisbider.com</a>> wrote:</div><br><div><div dir=3D"ltr"><=
div>In practical observation on x64 Windows,=C2=A0memcpy is 2 - 9 times fas=
ter than a loop of placement new followed by destructor.</div></div></div><=
/blockquote><div><br></div><div>=E2=80=9CPlacement new=E2=80=9D means calli=
ng a constructor. Yes, it=E2=80=99s possible to write a benchmark with cons=
tructors which goes faster when they=E2=80=99re not called. That doesn=E2=
=80=99t make the optimization valid.</div><br><blockquote type=3D"cite"><di=
v dir=3D"ltr"><div>The greatest speedup - factor of 5-9 -=C2=A0is with comm=
only used container sizes of 100 - 1000 objects.</div><div><br></div><div><=
br></div><div>>=C2=A0 nothing is stopping the compiler from detecting th=
at</div><div>> it=E2=80=99s nothing but a sequence of <font face=3D"Cour=
ier">memcpy</font> calls</div><div><br></div><div>Nothing is stopping the c=
ompiler, except for that it isn't yet a fully evolved AI, </div></div><=
/blockquote><div><br></div><div>Well, Clang at least does a pretty good job=
:=C2=A0<a onmousedown=3D"this.href=3D'http://goo.gl/x188jS';return =
true;" onclick=3D"this.href=3D'http://goo.gl/x188jS';return true;" =
href=3D"http://goo.gl/x188jS" target=3D"_blank" rel=3D"nofollow">http://goo=
..gl/x188jS</a>=C2=A0(<a onmousedown=3D"this.href=3D'http://www.google.c=
om/url?q\75http%3A%2F%2Fgodbolt.org\46sa\75D\46sntz\0751\46usg\75AFQjCNFYTq=
Gkg0_E6G6-ykgauFNBAjjhbw';return true;" onclick=3D"this.href=3D'htt=
p://www.google.com/url?q\75http%3A%2F%2Fgodbolt.org\46sa\75D\46sntz\0751\46=
usg\75AFQjCNFYTqGkg0_E6G6-ykgauFNBAjjhbw';return true;" href=3D"http://=
godbolt.org" target=3D"_blank" rel=3D"nofollow">god<wbr>bolt.org</a> link)<=
/div><div><br></div><div>The other compilers there aren=E2=80=99t too shabb=
y either. Can=E2=80=99t speak for MSVC.</div><br><blockquote type=3D"cite">=
<div dir=3D"ltr"><div>and relies on humans to craft optimization rules that=
fail about as often as they succeed, subject to quirky conditions;=C2=A0an=
d=C2=A0the developer has no way of knowing which is going to happen in adva=
nce.</div><div><br></div><div>One of the main=C2=A0advantages=C2=A0of=C2=A0=
C++=C2=A0is that it does <em>not</em> separate the developer=C2=A0from the =
platform, and does not require trusting complex infrastructure to either op=
timize code, or fail to. </div></div></blockquote><div><br></div><div>In th=
at case, my proposal shouldn=E2=80=99t interfere with the motivation for yo=
ur effort to make a trait that automatically computes whether a class is co=
mpatible with <font face=3D"Courier">realloc</font>.</div><div><br></div><d=
iv>However, it sounds like the language you=E2=80=99re describing is C (wit=
h optimizations disabled), not C++.</div><div><br></div></div></div></block=
quote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1174_1284991292.1438541900595--
------=_Part_1173_304098463.1438541900595--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 2 Aug 2015 22:18:12 +0300
Raw View
On 2 August 2015 at 21:58, denis bider <isocppgroup@denisbider.com> wrote:
> This is a violation of common sense, a humiliation for C++, and proof that
> the language is being run by people out of touch with the world.
While you're at it, I recommend remembering that C++ is not run by the people
on this forum.
When it comes to destructive move, I want to see Pablo's follow-up, because he
and Chandler were tasked to look at whether the destructive moves the proposed
are truly necessary. If you think you have useful material for such a
follow-up, talk to him.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 02 Aug 2015 12:36:48 -0700
Raw View
On Sunday 02 August 2015 11:58:20 denis bider wrote:
> This is a violation of common sense, a humiliation for C++, and proof that
> the language is being run by people out of touch with the world.
Denis, please stop attacking the people behind ideas. You can be as much frank
as you want on technical terms, but the moment that you resort to attacking
people, you lose credit.
I've been supporting your proposal so far, but if this continues I will stop
reading your emails.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 3 Aug 2015 11:59:25 +0800
Raw View
--Apple-Mail=_C9CD3DD2-EC3F-4F53-BAAD-777BD013E885
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9303, at 2:58 AM, denis bider <isocppgroup@denis=
bider.com> wrote:
>=20
> What you're doing is forcing all objects that want to implement relocatio=
n to split their data members into a base away from the code, and then to n=
ominate that base for destructive moving.
It=E2=80=99s a trade-off between alternatives:
1. Enable destructive move only by a trait, only when it=E2=80=99s trivial.=
Classes that would be nontrivially destructive movable get nothing. The tr=
ait is supposed to be computed magically somehow, so classes aren=E2=80=99t=
aware of their own triviality. This seems to be your direction, because yo=
u haven=E2=80=99t acknowledged the possibility of nontriviality.
2. Require the user to write their own overload of uninitialized_destructiv=
e_move when it=E2=80=99s nontrivial. This overload needs to dance around th=
e object lifetime model, which requires a __COOKIE__. It needs to implement=
the parts of the move constructor and destructor which remain necessary, w=
hich can be tricky. This is demonstrated in N4393.
3. Try to make an uninitialized_destructive_move template which works in th=
e nontrivial case, by letting the class slice its own move constructor and =
destructor. If a class wants to refine its own lifetime semantics, that=E2=
=80=99s its own responsibility.
> You are doing this to shoehorn support for relocation, while preserving a=
conceptual language deficiency in place.
The object lifetime model is not a language deficiency, it=E2=80=99s a corn=
erstone. The reason I CC=E2=80=99ed Ville is that he often has insightful o=
pinions about destructors.
> You're doing this to work around the status quo, but while you do so, you=
don't even benefit from not having to change the language. You're still ha=
ving to change the language, in order to allow slicing to work in the first=
place.
No, slicing already works. You can already try my proposal by using the syn=
tax derived_ptr->base::~base(). No UB happens until you create a new object=
at the derived_ptr address, and it only makes a difference if you=E2=80=99=
re running a sanitizer that exhaustively tracks object lifetimes (or the im=
plementation otherwise does so, which would be quite exotic).
My proposed language change is to allow users to do the same thing, without=
incurring a sanitizer=E2=80=99s wrath. I picked a currently disallowed syn=
tax derived_ptr->~base() to avoid breaking the very narrow use case where t=
he user destroys a base subobject yet continues to call member functions on=
the derived object (which has absolutely no remaining state!).
> You are doing all of this, for the sole and only purpose of having this:
>=20
> T* holy_blessed_relocate(void* d, T* s, size_t n) {
No, I=E2=80=99m doing it to avoid requiring the user to write their own unh=
oly_destructive_move which, as reflected in N4393 =C2=A74.1=E2=80=99s examp=
le of nontriviality, is likely to forget to call member destructors that ma=
y actually be necessary.
The tendency to forget nontriviality is a force to be reckoned with. I thin=
k it=E2=80=99s fundamentally what=E2=80=99s driving your opposition here. Y=
ou want things to be trivial. But, destructors shouldn=E2=80=99t be ignored=
so easily.
> These lines of code is the whole difference your slicing approach boils d=
own to.
>=20
> In exchange for this, you are asking everyone in the world to pay for you=
r "conceptual beauty" - such as it is - by forcing them to separate their r=
elocatable implementations into two separate objects.
Everyone in the world shouldn=E2=80=99t be implementing data structure clas=
ses. As I describe in =C2=A73.1 of my latest draft, applicable classes alre=
ady tend to have separation of such concerns. =E2=80=9CIf these libraries w=
ished to optimize their lists, it could be done without introducing new cla=
sses or breaking the library ABI.=E2=80=9D
> This is a violation of common sense, a humiliation for C++, and proof tha=
t the language is being run by people out of touch with the world.
So far, I=E2=80=99ve dug into some standard library implementations and wor=
ked through a disassembly example. What real-world analysis are you bringin=
g to this discussion?
I didn=E2=80=99t consider composition of destructive-movable objects, thoug=
h. std::pair<std::string, std::string> should be destructive movable. My dr=
aft proposal really doesn=E2=80=99t handle this. N4393 handles it in the tr=
ivial case, given trait specialization.
> Whether we call holy_blessed_relocate<T> implemented one way, or the othe=
r way, static analysis tools continue to work exactly the same. The only di=
fference is a trivial implementation detail. And the cost you're paying for=
this detail is to make all the rest of the code ugly.
Of more concern here is dynamic analysis, which might detect that a lifetim=
e hasn=E2=80=99t properly ended. That=E2=80=99s the motivation behind __COO=
KIE__. If it weren=E2=80=99t for that, N4158 probably wouldn=E2=80=99t have=
led to N4393.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_C9CD3DD2-EC3F-4F53-BAAD-777BD013E885
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=
=E2=80=9303, at 2:58 AM, denis bider <<a href=3D"mailto:isocppgroup@deni=
sbider.com" class=3D"">isocppgroup@denisbider.com</a>> wrote:</div></blo=
ckquote><blockquote type=3D"cite" class=3D""><br class=3D""></blockquote><b=
lockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><div class=3D"">What you're doing is forcing<span =
class=3D"Apple-converted-space"> </span><strong class=3D"">all</strong=
><span class=3D"Apple-converted-space"> </span>objects that want to im=
plement relocation to split their data members into a base away from the co=
de, and then to nominate that base for destructive moving.</div><div class=
=3D""></div></div></div></blockquote><div><br class=3D""></div><div>It=E2=
=80=99s a trade-off between alternatives:</div><div><br class=3D""></div><d=
iv>1. Enable destructive move only by a trait, only when it=E2=80=99s trivi=
al. Classes that would be nontrivially destructive movable get nothing. The=
trait is supposed to be computed magically somehow, so classes aren=E2=80=
=99t aware of their own triviality. This seems to be your direction, becaus=
e you haven=E2=80=99t acknowledged the possibility of nontriviality.</div><=
div><br class=3D""></div><div>2. Require the user to write their own overlo=
ad of <font face=3D"Courier" class=3D"">uninitialized_destructive_move</fon=
t> when it=E2=80=99s nontrivial. This overload needs to dance around the ob=
ject lifetime model, which requires a <font face=3D"Courier" class=3D""><i =
class=3D"">__COOKIE__</i></font>. It needs to implement the parts of the mo=
ve constructor and destructor which remain necessary, which can be tricky. =
This is demonstrated in N4393.</div><div><br class=3D""></div><div>3. Try t=
o make an <font face=3D"Courier" class=3D"">uninitialized_destructive_=
move</font> template which works in the nontrivial case, by letting th=
e class slice its own move constructor and destructor. If a class wants to =
refine its own lifetime semantics, that=E2=80=99s its own responsibility.</=
div><div><br class=3D""></div><blockquote type=3D"cite" class=3D""><div cla=
ss=3D""><div dir=3D"ltr" style=3D"font-family: Helvetica; font-size: 12px; =
font-style: normal; font-variant: normal; font-weight: normal; letter-spaci=
ng: normal; line-height: normal; orphans: auto; text-align: start; text-ind=
ent: 0px; text-transform: none; white-space: normal; widows: auto; word-spa=
cing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><div class=3D"">You =
are doing this to shoehorn support for relocation, while preserving a =
conceptual language deficiency in place. </div></div></div></blockquote><di=
v><br class=3D""></div><div>The object lifetime model is not a language def=
iciency, it=E2=80=99s a cornerstone. The reason I CC=E2=80=99ed Ville is th=
at he often has insightful opinions about destructors.</div><br class=3D"">=
<blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><div class=3D"">You're doing this to work around t=
he status quo, but while you do so, you don't even benefit from not having =
to change the language. You're<span class=3D"Apple-converted-space"> <=
/span><em class=3D"">still</em><span class=3D"Apple-converted-space"> =
</span>having to change the language, in order to allow slicing to work in =
the first place.</div><div class=3D""></div></div></div></blockquote><div><=
br class=3D""></div><div>No, slicing already works. You can already try my =
proposal by using the syntax <font face=3D"Courier" class=3D"">derived_ptr-=
>base::~base()</font>. No UB happens until you create a new object at th=
e <span style=3D"font-family: Courier;" class=3D"">derived_ptr</span>&=
nbsp;address, and it only makes a difference if you=E2=80=99re running a sa=
nitizer that exhaustively tracks object lifetimes (or the implementation ot=
herwise does so, which would be quite exotic).</div><div><br class=3D""></d=
iv><div>My proposed language change is to allow users to do the same thing,=
without incurring a sanitizer=E2=80=99s wrath. I picked a currently disall=
owed syntax <font face=3D"Courier" class=3D"">derived_ptr->~base()</font=
> to avoid breaking the very narrow use case where the user destroys a=
base subobject yet continues to call member functions on the derived objec=
t (which has absolutely no remaining state!).</div><br class=3D""><blockquo=
te type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" style=3D"font-=
family: Helvetica; font-size: 12px; font-style: normal; font-variant: norma=
l; letter-spacing: normal; line-height: normal; orphans: auto; text-align: =
start; text-indent: 0px; text-transform: none; white-space: normal; widows:=
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; font-weight: norm=
al;" class=3D""><div class=3D"">You are doing all of this, for the sol=
e and only purpose of having this:</div><div class=3D""><br class=3D""=
></div><div class=3D""><span style=3D"color: rgb(0, 0, 32); background-colo=
r: rgb(246, 248, 255);" class=3D"">T</span><span class=3D"" style=3D"backgr=
ound-color: rgb(246, 248, 255); color: rgb(48, 128, 128);">*</span><span st=
yle=3D"color: rgb(0, 0, 32); background-color: rgb(246, 248, 255);" class=
=3D""> holy_blessed_relocate</span><span class=3D"" style=3D"background-col=
or: rgb(246, 248, 255); color: rgb(48, 128, 128);">(</span><span class=3D""=
style=3D"background-color: rgb(246, 248, 255); color: rgb(32, 0, 128); fon=
t-weight: bold;">void</span><span class=3D"" style=3D"background-color: rgb=
(246, 248, 255); color: rgb(48, 128, 128);">*</span><span style=3D"color: r=
gb(0, 0, 32); background-color: rgb(246, 248, 255);" class=3D""> d</span><s=
pan class=3D"" style=3D"background-color: rgb(246, 248, 255); color: rgb(48=
, 128, 128);">,</span><span style=3D"color: rgb(0, 0, 32); background-color=
: rgb(246, 248, 255);" class=3D""> T</span><span class=3D"" style=3D"backgr=
ound-color: rgb(246, 248, 255); color: rgb(48, 128, 128);">*</span><span st=
yle=3D"color: rgb(0, 0, 32); background-color: rgb(246, 248, 255);" class=
=3D""> s</span><span class=3D"" style=3D"background-color: rgb(246, 248, 25=
5); color: rgb(48, 128, 128);">,</span><span style=3D"color: rgb(0, 0, 32);=
background-color: rgb(246, 248, 255);" class=3D""> </span><span class=3D""=
style=3D"background-color: rgb(246, 248, 255); color: rgb(0, 48, 96);">siz=
e_t</span><span style=3D"color: rgb(0, 0, 32); background-color: rgb(246, 2=
48, 255);" class=3D""> n</span><span class=3D"" style=3D"background-color: =
rgb(246, 248, 255); color: rgb(48, 128, 128);">)</span><span style=3D"color=
: rgb(0, 0, 32); background-color: rgb(246, 248, 255);" class=3D""> </span>=
<span class=3D"" style=3D"background-color: rgb(246, 248, 255); color: rgb(=
64, 96, 128);">{<br class=3D""></span></div></div></div></blockquote><div><=
br class=3D""></div><div>No, I=E2=80=99m doing it to avoid requiring the us=
er to write their own <font face=3D"Courier" class=3D"">unholy_destructive_=
move</font> which, as reflected in N4393 =C2=A74.1=E2=80=99s example o=
f nontriviality, is likely to forget to call member destructors that may ac=
tually be necessary.</div><div><br class=3D""></div><div>The tendency to fo=
rget nontriviality is a force to be reckoned with. I think it=E2=80=99s fun=
damentally what=E2=80=99s driving your opposition here. You <i class=3D"">w=
ant</i> things to be trivial. But, destructors shouldn=E2=80=99t be ig=
nored so easily.</div><br class=3D""><blockquote type=3D"cite" class=3D""><=
div class=3D""><div dir=3D"ltr" style=3D"font-family: Helvetica; font-size:=
12px; font-style: normal; font-variant: normal; letter-spacing: normal; li=
ne-height: normal; orphans: auto; text-align: start; text-indent: 0px; text=
-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -we=
bkit-text-stroke-width: 0px; font-weight: normal;" class=3D""><div class=3D=
"">These lines of code is the whole difference your slicing appro=
ach boils down to.</div></div></div></blockquote><blockquote type=3D"cite" =
class=3D""><div dir=3D"ltr" style=3D"font-family: Helvetica; font-size: 12p=
x; font-style: normal; font-variant: normal; letter-spacing: normal; line-h=
eight: normal; orphans: auto; text-align: start; text-indent: 0px; text-tra=
nsform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit=
-text-stroke-width: 0px; font-weight: normal;" class=3D""><div class=3D""><=
br class=3D""></div><div class=3D"">In exchange for this, you are asking<sp=
an class=3D"Apple-converted-space"> </span><em class=3D"">everyone in =
the world</em><span class=3D"Apple-converted-space"> </span>to pay for=
your "conceptual beauty" - such as it is - by forcing them to separat=
e their relocatable implementations into two separate objects.</div><div cl=
ass=3D""></div></div></blockquote><div><br class=3D""></div><div>Everyone i=
n the world shouldn=E2=80=99t be implementing data structure classes. As I =
describe in =C2=A73.1 of my latest draft, applicable classes already tend t=
o have separation of such concerns. =E2=80=9CIf these libraries wished to o=
ptimize their <font face=3D"Courier" class=3D"">list</font>s, it could=
be done without introducing new classes or breaking the library ABI.=E2=80=
=9D</div><br class=3D""><blockquote type=3D"cite" class=3D""><div dir=3D"lt=
r" style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; fo=
nt-variant: normal; letter-spacing: normal; line-height: normal; orphans: a=
uto; text-align: start; text-indent: 0px; text-transform: none; white-space=
: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
font-weight: normal;" class=3D""><div class=3D"">This is a violation of com=
mon sense, a humiliation for C++, and proof that the language is being=
run by people out of touch with the world.</div><div class=3D""></div></di=
v></blockquote><div><br class=3D""></div><div>So far, I=E2=80=99ve dug into=
some standard library implementations and worked through a disassembly exa=
mple. What real-world analysis are you bringing to this discussion?</div><d=
iv><br class=3D""></div><div>I didn=E2=80=99t consider composition of destr=
uctive-movable objects, though. <font face=3D"Courier" class=3D"">std::pair=
<std::string, std::string></font> should be destructive movable. My d=
raft proposal really doesn=E2=80=99t handle this. N4393 handles it in the t=
rivial case, given trait specialization.</div><br class=3D""><blockquote ty=
pe=3D"cite" class=3D""><div dir=3D"ltr" style=3D"font-family: Helvetica; fo=
nt-size: 12px; font-style: normal; font-variant: normal; letter-spacing: no=
rmal; line-height: normal; orphans: auto; text-align: start; text-indent: 0=
px; text-transform: none; white-space: normal; widows: auto; word-spacing: =
0px; -webkit-text-stroke-width: 0px; font-weight: normal;" class=3D""><div =
class=3D"">Whether we call<span class=3D"Apple-converted-space"> </spa=
n><font face=3D"courier new,monospace" class=3D"">holy_blessed_relocate<=
T></font><span class=3D"Apple-converted-space"> </span>implemented =
one way, or the other way, static analysis tools continue to work exactly t=
he same. The<span class=3D"Apple-converted-space"> </span><em class=3D=
"">only</em><span class=3D"Apple-converted-space"> </span>difference i=
s a trivial implementation detail. And the cost you're paying for this=
detail is to make all the<span class=3D"Apple-converted-space">&=
nbsp;</span><em class=3D"">rest</em><span class=3D"Apple-converted-space">&=
nbsp;</span>of the code ugly.</div></div></blockquote></div><br class=3D"">=
<div class=3D"">Of more concern here is dynamic analysis, which might detec=
t that a lifetime hasn=E2=80=99t properly ended. That=E2=80=99s the motivat=
ion behind <font face=3D"Courier" class=3D""><i class=3D"">__COOKIE__<=
/i></font>. If it weren=E2=80=99t for that, N4158 probably wouldn=E2=80=99t=
have led to N4393.</div><div class=3D""><br class=3D""></div></body></html=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_C9CD3DD2-EC3F-4F53-BAAD-777BD013E885--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 3 Aug 2015 12:20:59 +0800
Raw View
> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <ville.vouti=
lainen@gmail.com> wrote:
>=20
> When it comes to destructive move, I want to see Pablo's follow-up, becau=
se he
> and Chandler were tasked to look at whether the destructive moves the pro=
posed
> are truly necessary. If you think you have useful material for such a
> follow-up, talk to him.
Is N4393 not that followup?
This is why I=E2=80=99m asking for feedback here (and CC=E2=80=99ing Pablo)=
.. This proposal is not my baby, and it can be stopped in its tracks if some=
one points out that something critical is missing. I=E2=80=99d prefer not t=
o waste effort developing something that=E2=80=99s doomed.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 3 Aug 2015 09:40:54 +0300
Raw View
On 3 August 2015 at 07:20, David Krauss <potswa@gmail.com> wrote:
>> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <ville.vout=
ilainen@gmail.com> wrote:
>> When it comes to destructive move, I want to see Pablo's follow-up, beca=
use he
>> and Chandler were tasked to look at whether the destructive moves the pr=
oposed
>> are truly necessary. If you think you have useful material for such a
>> follow-up, talk to him.
> Is N4393 not that followup?
No, we looked at N4393 in Lenexa and gave the paper author some homework to=
do.
So that would be a follow-up subsequent to N4393.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Mon, 3 Aug 2015 09:56:15 +0100
Raw View
--001a113369e89659ed051c64574a
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
There's a couple of things I dislike of David Krauss' proposal, while I
understand that it is an attempt to make something work in a much simpler
way than the alternatives in the language.
I dislike forcing the design of the types into a base with members and a
derived type with functionality on purely theoretical grounds (was this the
only concern I may swallow those), but in forcing a particular layout of
the members and code I feel it inhibits non-trivial uses. I don't see, for
example, how composibility could be obtained. In the libraries that offer
relocability through traits this is easily handled in BSL:
template <typename T, typename U>
struct is_relocatable<pair<T,U>>
: integral_constant<bool, is_relocatable<T>::value
&& is_relocatable<U>::value>
{};
BSL:
https://github.com/bloomberg/bde/blob/master/groups/bsl/bslstl/bslstl_pair.=
h#L1015
EASTL does not try to infer the relocatability of a generic type out of the
members.
FB Folly aims to detect the trait through indirect checks on the type, but
not from the members; it does not provide many generic types (at least no
pair, which is what I looked for)
I have not checked Qt (not familiar with the codebase).
This works easily as memcpy over the pair is roughly equivalent to memcpy
of both members (ignoring padding here, but it should be fine to ignore
padding). I don't quite see how you could do the same with the proposed
alternative. What would the implementation of pair need to do?
I believe that from a user's point of view (more people will develop code
than the standard), the simplest approach is what current libraries do: the
user that creates a type need only provide the trait, the library does the
rest of the work and that work is minimal at the library level. Requiring
that the movable type is split hierarchically in a particular way forces a
redesign on user types that I don't quite like.
Beyond that approach, the no-op construction/destruction imposes a bit more
work on the library, but still there are far less implementors of
containers than general types so the burden is still small: the library
needs to add some code to instruct the compiler/analyzers of lifetime
changes. Compilers should not have any trouble optimizing the loops of
no-op construction/destruction and while those look like real code they
become no more than annotations [should we maybe consider using some form
of annotation rather than the loop?]
David's approach here is the one that makes this available in the shorter
term (the impact on the standard is small enough that reasoning about it is
simple and, I think we can agree, safe). But at the same time it is the
most expensive alternative of the three for developers, and not trivial to
use (not only for the library implementor, but also for the implementor of
the relocatable types).
If the other approaches hit a wall and cannot proceed, David's approach is
better than nothing, but I'd rather get something less intrusive on user
code.
David
On Mon, Aug 3, 2015 at 7:40 AM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:
> On 3 August 2015 at 07:20, David Krauss <potswa@gmail.com> wrote:
> >> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <
> ville.voutilainen@gmail.com> wrote:
> >> When it comes to destructive move, I want to see Pablo's follow-up,
> because he
> >> and Chandler were tasked to look at whether the destructive moves the
> proposed
> >> are truly necessary. If you think you have useful material for such a
> >> follow-up, talk to him.
> > Is N4393 not that followup?
>
> No, we looked at N4393 in Lenexa and gave the paper author some homework
> to do.
> So that would be a follow-up subsequent to N4393.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a113369e89659ed051c64574a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">There's a couple of things I dislike of David Krauss&#=
39; proposal, while I understand that it is an attempt to make something wo=
rk in a much simpler way than the alternatives in the language.<br><br>I di=
slike forcing the design of the types into a base with members and a derive=
d type with functionality on purely theoretical grounds (was this the only =
concern I may swallow those), but in forcing a particular layout of the mem=
bers and code I feel it inhibits non-trivial uses. I don't see, for exa=
mple, how composibility could be obtained. In the libraries that offer relo=
cability through traits this is easily handled in BSL:<br><br>template <=
typename T, typename U><br>struct is_relocatable<pair<T,U>> =
<br>: integral_constant<bool, is_relocatable<T>::value=C2=A0<div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&& is_relocatable<U>::v=
alue><div>{};</div><div><br>BSL: <a href=3D"https://github.com/bloomberg=
/bde/blob/master/groups/bsl/bslstl/bslstl_pair.h#L1015">https://github.com/=
bloomberg/bde/blob/master/groups/bsl/bslstl/bslstl_pair.h#L1015</a><br>EAST=
L does not try to infer the relocatability of a generic type out of the mem=
bers.<br>FB Folly aims to detect the trait through indirect checks on the t=
ype, but not from the members; it does not provide many generic types (at l=
east no pair, which is what I looked for)<br>I have not checked Qt (not fam=
iliar with the codebase).<br><br>This works easily as memcpy over the pair =
is roughly equivalent to memcpy of both members (ignoring padding here, but=
it should be fine to ignore padding). I don't quite see how you could =
do the same with the proposed alternative. What would the implementation of=
pair need to do?<br><br>I believe that from a user's point of view (mo=
re people will develop code than the standard), the simplest approach is wh=
at current libraries do: the user that creates a type need only provide the=
trait, the library does the rest of the work and that work is minimal at t=
he library level. Requiring that the movable type is split hierarchically i=
n a particular way forces a redesign on user types that I don't quite l=
ike.<br><br>Beyond that approach, the no-op construction/destruction impose=
s a bit more work on the library, but still there are far less implementors=
of containers than general types so the burden is still small: the library=
needs to add some code to instruct the compiler/analyzers of lifetime chan=
ges. Compilers should not have any trouble optimizing the loops of no-op co=
nstruction/destruction and while those look like real code they become no m=
ore than annotations [should we maybe consider using some form of annotatio=
n rather than the loop?]<br><br>David's approach here is the one that m=
akes this available in the shorter term (the impact on the standard is smal=
l enough that reasoning about it is simple and, I think we can agree, safe)=
.. But at the same time it is the most expensive alternative of the three fo=
r developers, and not trivial to use (not only for the library implementor,=
but also for the implementor of the relocatable types).<br><br>If the othe=
r approaches hit a wall and cannot proceed, David's approach is better =
than nothing, but I'd rather get something less intrusive on user code.=
<br><br>=C2=A0 =C2=A0 David</div></div></div><div class=3D"gmail_extra"><br=
><div class=3D"gmail_quote">On Mon, Aug 3, 2015 at 7:40 AM, Ville Voutilain=
en <span dir=3D"ltr"><<a href=3D"mailto:ville.voutilainen@gmail.com" tar=
get=3D"_blank">ville.voutilainen@gmail.com</a>></span> wrote:<br><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><span class=3D"">On 3 August 2015 at 07:20, David K=
rauss <<a href=3D"mailto:potswa@gmail.com">potswa@gmail.com</a>> wrot=
e:<br>
>> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <<=
a href=3D"mailto:ville.voutilainen@gmail.com">ville.voutilainen@gmail.com</=
a>> wrote:<br>
>> When it comes to destructive move, I want to see Pablo's follo=
w-up, because he<br>
>> and Chandler were tasked to look at whether the destructive moves =
the proposed<br>
>> are truly necessary. If you think you have useful material for suc=
h a<br>
>> follow-up, talk to him.<br>
> Is N4393 not that followup?<br>
<br>
</span>No, we looked at N4393 in Lenexa and gave the paper author some home=
work to do.<br>
So that would be a follow-up subsequent to N4393.<br>
<div class=3D"HOEnZb"><div class=3D"h5"><br>
--<br>
<br>
---<br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113369e89659ed051c64574a--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Mon, 3 Aug 2015 13:33:16 -0700 (PDT)
Raw View
------=_Part_643_1441466480.1438633996800
Content-Type: multipart/alternative;
boundary="----=_Part_644_750415446.1438633996801"
------=_Part_644_750415446.1438633996801
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I agree; I don't see how this proposal can compose types. If one of the=20
base class members is nontrivially destructively movable, this proposal=20
nevertheless calls its destructor so it needs to be in a destructible state=
..
To be useful (IMO), destructive move must automatically compose for record=
=20
types (i.e. structs without a user-declared destructor) as well as for pair=
and=20
tuple; it should be (reasonably) easy to customize for self-referential=20
types while optimizing to memcpy-equivalent for trivially destructive=20
movable types.
For example, struct employee should be efficiently destructively movable=20
despite containing one or more strings (which under=20
pointer-to-internal-buffer SSO require special handling); its automatically=
=20
generated destructive move should destructively move each data member in=20
turn, which might optimize to one big memcpy if string is not=20
pointer-to-internal-buffer SSO.
As I see it, this requires either a new category of special function (as=20
with the introduction of move constructors in C++11, so the Rule of Five=20
becomes a Rule of Six, or Seven if we're going to add a destructive move=20
assignment operator), *or* introspection facilities such that Pablo's unini=
tialized_destructive_move=20
(n4158) can recurse on bases and members.
For the former (strawman syntax):
struct A { int i; };
struct B : A { ~B() {} B~(B const&) =3D default; };
struct C { B m; int* p =3D &m.A::i; C~(C const& rhs) : m~{rhs.m}, p{&m.A::i=
}=20
{} };
void f() {
char* storage =3D new char[sizeof C];
C* p =3D new (storage) C;
C c ~ *p; // destructive move construction; ends lifetime of *p
delete[] storage;
}
Here the destructive move constructor T::T~(T const&) is automatically=20
defined as defaulted if T has no user-declared copy constructor, no=20
user-declared move constructor, and no user-declared destructor. The=20
initializers ~ expression and ~{ *initializer-list* } call a destructive=20
move constructor if available, otherwise a copy constructor followed by=20
destruction of the argument.
For the latter, the optimized variant of uninitialized_destructive_move(T*=
=20
from, T* to) would become:
new (to) T(__COOKIE__);
for_each_base<T>([&](auto base_ptr) { uninitialized_destructive_move(&from
->*base_ptr, &to->*base_ptr); });
for_each_member<T>([&](auto mem_ptr) { uninitialized_destructive_move(&from
->*mem_ptr, &to->*mem_ptr); });
from->~T(__COOKIE__);
This would be created automatically if T has no user-declared copy=20
constructor, no user-declared move constructor, and no user-declared=20
destructor, or on an opt-in basis (via is_memberwise_destructive_movable?).
In either case new core language is required; less in the latter case (as=
=20
long as you count introspection as being outside core).
On Monday, 3 August 2015 09:56:18 UTC+1, David Rodr=C3=ADguez Ibeas wrote:
>
> There's a couple of things I dislike of David Krauss' proposal, while I=
=20
> understand that it is an attempt to make something work in a much simpler=
=20
> way than the alternatives in the language.
>
> I dislike forcing the design of the types into a base with members and a=
=20
> derived type with functionality on purely theoretical grounds (was this t=
he=20
> only concern I may swallow those), but in forcing a particular layout of=
=20
> the members and code I feel it inhibits non-trivial uses. I don't see, fo=
r=20
> example, how composibility could be obtained. In the libraries that offer=
=20
> relocability through traits this is easily handled in BSL:
>
> template <typename T, typename U>
> struct is_relocatable<pair<T,U>>=20
> : integral_constant<bool, is_relocatable<T>::value=20
> && is_relocatable<U>::value>
> {};
>
> BSL:=20
> https://github.com/bloomberg/bde/blob/master/groups/bsl/bslstl/bslstl_pai=
r.h#L1015
> EASTL does not try to infer the relocatability of a generic type out of=
=20
> the members.
> FB Folly aims to detect the trait through indirect checks on the type, bu=
t=20
> not from the members; it does not provide many generic types (at least no=
=20
> pair, which is what I looked for)
> I have not checked Qt (not familiar with the codebase).
>
> This works easily as memcpy over the pair is roughly equivalent to memcpy=
=20
> of both members (ignoring padding here, but it should be fine to ignore=
=20
> padding). I don't quite see how you could do the same with the proposed=
=20
> alternative. What would the implementation of pair need to do?
>
> I believe that from a user's point of view (more people will develop code=
=20
> than the standard), the simplest approach is what current libraries do: t=
he=20
> user that creates a type need only provide the trait, the library does th=
e=20
> rest of the work and that work is minimal at the library level. Requiring=
=20
> that the movable type is split hierarchically in a particular way forces =
a=20
> redesign on user types that I don't quite like.
>
> Beyond that approach, the no-op construction/destruction imposes a bit=20
> more work on the library, but still there are far less implementors of=20
> containers than general types so the burden is still small: the library=
=20
> needs to add some code to instruct the compiler/analyzers of lifetime=20
> changes. Compilers should not have any trouble optimizing the loops of=20
> no-op construction/destruction and while those look like real code they=
=20
> become no more than annotations [should we maybe consider using some form=
=20
> of annotation rather than the loop?]
>
> David's approach here is the one that makes this available in the shorter=
=20
> term (the impact on the standard is small enough that reasoning about it =
is=20
> simple and, I think we can agree, safe). But at the same time it is the=
=20
> most expensive alternative of the three for developers, and not trivial t=
o=20
> use (not only for the library implementor, but also for the implementor o=
f=20
> the relocatable types).
>
> If the other approaches hit a wall and cannot proceed, David's approach i=
s=20
> better than nothing, but I'd rather get something less intrusive on user=
=20
> code.
>
> David
>
> On Mon, Aug 3, 2015 at 7:40 AM, Ville Voutilainen <ville.vo...@gmail.com=
=20
> <javascript:>> wrote:
>
>> On 3 August 2015 at 07:20, David Krauss <pot...@gmail.com <javascript:>>=
=20
>> wrote:
>> >> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <ville.v=
o...@gmail.com=20
>> <javascript:>> wrote:
>> >> When it comes to destructive move, I want to see Pablo's follow-up,=
=20
>> because he
>> >> and Chandler were tasked to look at whether the destructive moves the=
=20
>> proposed
>> >> are truly necessary. If you think you have useful material for such a
>> >> follow-up, talk to him.
>> > Is N4393 not that followup?
>>
>> No, we looked at N4393 in Lenexa and gave the paper author some homework=
=20
>> to do.
>> So that would be a follow-up subsequent to N4393.
>>
>> --
>>
>> ---
>> You received this message because you are subscribed to the Google Group=
s=20
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n=20
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at=20
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_644_750415446.1438633996801
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I agree; I don't see how this proposal can compose typ=
es. If one of the base class members is nontrivially destructively movable,=
this proposal nevertheless calls its destructor so it needs to be in a des=
tructible state.<div><br></div><div>To be useful (IMO), destructive move mu=
st automatically compose for record types (i.e. <font face=3D"courier new, =
monospace">struct</font>s without a user-declared destructor) as well as fo=
r <font face=3D"courier new, monospace">pair </font>and <font face=3D"couri=
er new, monospace">tuple</font>; it should be (reasonably) easy to customiz=
e for self-referential types while optimizing to <font face=3D"courier new,=
monospace">memcpy</font>-equivalent for trivially destructive movable type=
s.</div><div><br></div><div>For example, <font face=3D"courier new, monospa=
ce">struct employee</font> should be efficiently destructively movable desp=
ite containing one or more <font face=3D"courier new, monospace">string</fo=
nt>s (which under pointer-to-internal-buffer SSO require special handling);=
its automatically generated destructive move should destructively move eac=
h data member in turn, which might optimize to one big=C2=A0<font face=3D"c=
ourier new, monospace">memcpy </font>if <font face=3D"courier new, monospac=
e">string </font>is not pointer-to-internal-buffer SSO.</div><div><div><br>=
</div><div>As I see it, this requires either a new category of special func=
tion (as with the introduction of move constructors in C++11, so the Rule o=
f Five becomes a Rule of Six, or Seven if we're going to add a destruct=
ive move assignment operator), <i>or</i> introspection facilities such that=
Pablo's <font face=3D"courier new, monospace">uninitialized_destructiv=
e_move </font>(n4158) can recurse on bases and members.</div><div><br></div=
><div>For the former (strawman syntax):</div><div><br></div><div class=3D"p=
rettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break=
-word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> A </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> B </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> A </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">~</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">B</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
B</span><span style=3D"color: #660;" class=3D"styled-by-prettify">~(</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">B </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&)</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">default</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">};<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> C </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> B m</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
p </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">m</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">A</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">i</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> C</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">~(</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">C </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> rhs</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> m</span><span style=3D"color: #660;" class=3D"styled-by-prettify">~{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">rhs</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">m</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">},</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> p</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{&</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">m</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">A</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">i</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> f</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> storage </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">new</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">char</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> C</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">];</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 C</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> p </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">new</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">storage</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> C</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 C c </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">~</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0</span><s=
pan style=3D"color: #800;" class=3D"styled-by-prettify">// destructive move=
construction; ends lifetime of *p</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">delete</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">[]</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> storage</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></=
div></code></div><div><br></div><div>Here the destructive move constructor =
<font face=3D"courier new, monospace">T::T~(T const&)</font> is automat=
ically defined as defaulted if=C2=A0<font face=3D"courier new, monospace">T=
</font> has no user-declared copy constructor, no user-declared move constr=
uctor, and no user-declared destructor. The initializers <font face=3D"cour=
ier new, monospace">~ expression</font> and <font face=3D"courier new, mono=
space">~{</font> <i>initializer-list</i> <font face=3D"courier new, monospa=
ce">}</font> call a destructive move constructor if available, otherwise a =
copy constructor followed by destruction of the argument.</div><div><br>For=
the latter, the optimized variant of=C2=A0<font face=3D"courier new, monos=
pace">uninitialized_destructive_move(T* from, T* to)</font> =C2=A0would bec=
ome:</div><div><br></div><div class=3D"prettyprint" style=3D"border: 1px so=
lid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 2=
50, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span =
style=3D"color: #008;" class=3D"styled-by-prettify">new</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">to</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">__COO=
KIE__</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>for_each_=
base</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">>([&](</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> base_ptr</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> uninitialized_destructive_move</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(&</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">from</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">->*</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">base_ptr</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">to</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">->*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ba=
se_ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">});</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>for_each_member</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">>([&](</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> mem_ptr</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> uninitialized_destructive_move</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(&</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">from</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">->*</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">mem_ptr</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">to</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">->*</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">mem_ptr</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">});</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">from</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">->~</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">__COOKIE=
__</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div=
></code></div><div><br></div><div>This would be created automatically if=C2=
=A0<font face=3D"courier new, monospace">T</font> has no user-declared copy=
constructor, no user-declared move constructor, and no user-declared destr=
uctor, or on an opt-in basis (via <font face=3D"courier new, monospace">is_=
memberwise_destructive_movable</font>?).<br></div><div><br>In either case n=
ew core language is required; less in the latter case (as long as you count=
introspection as being outside core).<br></div><div><br>On Monday, 3 Augus=
t 2015 09:56:18 UTC+1, David Rodr=C3=ADguez Ibeas wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr">There's a couple of things=
I dislike of David Krauss' proposal, while I understand that it is an =
attempt to make something work in a much simpler way than the alternatives =
in the language.<br><br>I dislike forcing the design of the types into a ba=
se with members and a derived type with functionality on purely theoretical=
grounds (was this the only concern I may swallow those), but in forcing a =
particular layout of the members and code I feel it inhibits non-trivial us=
es. I don't see, for example, how composibility could be obtained. In t=
he libraries that offer relocability through traits this is easily handled =
in BSL:<br><br>template <typename T, typename U><br>struct is_relocat=
able<pair<T,U>> <br>: integral_constant<bool, is_relocatable=
<T>::value=C2=A0<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&& i=
s_relocatable<U>::value><div>{};</div><div><br>BSL: <a href=3D"htt=
ps://github.com/bloomberg/bde/blob/master/groups/bsl/bslstl/bslstl_pair.h#L=
1015" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'ht=
tps://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2Fbloomberg%2Fbde%2Fb=
lob%2Fmaster%2Fgroups%2Fbsl%2Fbslstl%2Fbslstl_pair.h%23L1015\46sa\75D\46snt=
z\0751\46usg\75AFQjCNEjWOpDFB26hv9qY4c_cc2nsFEZYQ';return true;" onclic=
k=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgithub.c=
om%2Fbloomberg%2Fbde%2Fblob%2Fmaster%2Fgroups%2Fbsl%2Fbslstl%2Fbslstl_pair.=
h%23L1015\46sa\75D\46sntz\0751\46usg\75AFQjCNEjWOpDFB26hv9qY4c_cc2nsFEZYQ&#=
39;;return true;">https://github.com/bloomberg/<wbr>bde/blob/master/groups/=
bsl/<wbr>bslstl/bslstl_pair.h#L1015</a><br>EASTL does not try to infer the =
relocatability of a generic type out of the members.<br>FB Folly aims to de=
tect the trait through indirect checks on the type, but not from the member=
s; it does not provide many generic types (at least no pair, which is what =
I looked for)<br>I have not checked Qt (not familiar with the codebase).<br=
><br>This works easily as memcpy over the pair is roughly equivalent to mem=
cpy of both members (ignoring padding here, but it should be fine to ignore=
padding). I don't quite see how you could do the same with the propose=
d alternative. What would the implementation of pair need to do?<br><br>I b=
elieve that from a user's point of view (more people will develop code =
than the standard), the simplest approach is what current libraries do: the=
user that creates a type need only provide the trait, the library does the=
rest of the work and that work is minimal at the library level. Requiring =
that the movable type is split hierarchically in a particular way forces a =
redesign on user types that I don't quite like.<br><br>Beyond that appr=
oach, the no-op construction/destruction imposes a bit more work on the lib=
rary, but still there are far less implementors of containers than general =
types so the burden is still small: the library needs to add some code to i=
nstruct the compiler/analyzers of lifetime changes. Compilers should not ha=
ve any trouble optimizing the loops of no-op construction/destruction and w=
hile those look like real code they become no more than annotations [should=
we maybe consider using some form of annotation rather than the loop?]<br>=
<br>David's approach here is the one that makes this available in the s=
horter term (the impact on the standard is small enough that reasoning abou=
t it is simple and, I think we can agree, safe). But at the same time it is=
the most expensive alternative of the three for developers, and not trivia=
l to use (not only for the library implementor, but also for the implemento=
r of the relocatable types).<br><br>If the other approaches hit a wall and =
cannot proceed, David's approach is better than nothing, but I'd ra=
ther get something less intrusive on user code.<br><br>=C2=A0 =C2=A0 David<=
/div></div></div><div><br><div class=3D"gmail_quote">On Mon, Aug 3, 2015 at=
7:40 AM, Ville Voutilainen <span dir=3D"ltr"><<a href=3D"javascript:" t=
arget=3D"_blank" gdf-obfuscated-mailto=3D"AVXtlnmFDwAJ" rel=3D"nofollow" on=
mousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"thi=
s.href=3D'javascript:';return true;">ville.vo...@gmail.com</a>><=
/span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><span>On 3 August 2015 at 0=
7:20, David Krauss <<a href=3D"javascript:" target=3D"_blank" gdf-obfusc=
ated-mailto=3D"AVXtlnmFDwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#=
39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&#=
39;;return true;">pot...@gmail.com</a>> wrote:<br>
>> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <<=
a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"AVXtlnmFD=
wAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';retu=
rn true;" onclick=3D"this.href=3D'javascript:';return true;">ville.=
vo...@gmail.com</a>> wrote:<br>
>> When it comes to destructive move, I want to see Pablo's follo=
w-up, because he<br>
>> and Chandler were tasked to look at whether the destructive moves =
the proposed<br>
>> are truly necessary. If you think you have useful material for suc=
h a<br>
>> follow-up, talk to him.<br>
> Is N4393 not that followup?<br>
<br>
</span>No, we looked at N4393 in Lenexa and gave the paper author some home=
work to do.<br>
So that would be a follow-up subsequent to N4393.<br>
<div><div><br>
--<br>
<br>
---<br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
AVXtlnmFDwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"AVXtlnmFDwAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=
=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';ret=
urn true;" onclick=3D"this.href=3D'http://groups.google.com/a/isocpp.or=
g/group/std-proposals/';return true;">http://groups.google.com/a/<wbr>i=
socpp.org/group/std-<wbr>proposals/</a>.<br>
</div></div></blockquote></div><br></div>
</blockquote></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_644_750415446.1438633996801--
------=_Part_643_1441466480.1438633996800--
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 4 Aug 2015 12:52:27 +0800
Raw View
--Apple-Mail=_05DA5FBC-086C-48BC-980D-F66B363CAE2B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9303, at 4:56 PM, David Rodr=C3=ADguez Ibeas <di=
beas@ieee.org <mailto:dibeas@ieee.org>> wrote:
>=20
> There's a couple of things I dislike of David Krauss' proposal, while I u=
nderstand that it is an attempt to make something work in a much simpler wa=
y than the alternatives in the language.
The priorities are:
1. Correctness. Generating wrong programs is taking a step backward.
2. Efficiency and generality. There are two dimensions of generalization: h=
andling nontrivial move-and-destroy, and handling composition.
3. Ease of use. =E2=80=9CSimplicity=E2=80=9D isn=E2=80=99t genuine if you n=
eed to work through details of the object model, such as manually computing=
is_pod.
> I dislike forcing the design of the types into a base with members and a =
derived type with functionality on purely theoretical grounds (was this the=
only concern I may swallow those), but in forcing a particular layout of t=
he members and code I feel it inhibits non-trivial uses. I don't see, for e=
xample, how composibility could be obtained. In the libraries that offer re=
locability through traits this is easily handled in BSL:
Yeah, composition seems to merit support.
Requiring the user to factor out the base is a positive aspect. If they don=
=E2=80=99t, the compiler still has to do something very similar behind the =
scenes. What gets initialized by __COOKIE__? A layout-compatible but trivia=
lly constructible class that hasn=E2=80=99t been declared. The language wor=
ks better when all the cards are on the table.
Factoring out a base class is pretty elementary. What=E2=80=99s the theoret=
ical objection? Don=E2=80=99t like to declare classes that aren=E2=80=99t p=
art of the public interface? That=E2=80=99s a general impediment to good OO=
design. Remember that this is a performance optimization. That alone puts =
aesthetics at risk, and something=E2=80=99s gotta give: The alternative is =
to open namespace std for the sake of adding a manual specialization.
There is one thing that can break when factoring a base. The type of addres=
s-of-member expressions &foo::mem becomes mem_t base::*, which doesn=E2=80=
=99t implicitly convert back to the original type mem_t derived::*. Perhaps=
this should be revisited; AFAIK it=E2=80=99s only done that way for ease o=
f implementation and it often causes headaches when using PTMs.
Back to composition: If the base class is required to be an aggregate, then=
it=E2=80=99s not too =E2=80=9Cdirty=E2=80=9D to let destructive move const=
ruction propagate down to its members. As for the mechanics of that, I=E2=
=80=99ll have to let this simmer on the back burner for a little while.
> I believe that from a user's point of view (more people will develop code=
than the standard), the simplest approach is what current libraries do: th=
e user that creates a type need only provide the trait, the library does th=
e rest of the work and that work is minimal at the library level. Requiring=
that the movable type is split hierarchically in a particular way forces a=
redesign on user types that I don't quite like.
The trait is ugly and tricky to declare (sacrifice #3 ease) and tricky to s=
pecify (you need to remember to compose the types of all the members, sacri=
fice #1 correctness). Doubly so for traits of templates. The trait only cov=
ers the trivial case, otherwise you need to reimplement the destructive mov=
e algorithm (sacrifice #2 generality or double down on sacrifices of #1 and=
#3).
The established practice of libraries is a local optimum for metaprogrammin=
g. Adding a feature to the core language should be a deeper process than in=
ternalizing a metaprogram.
> David's approach here is the one that makes this available in the shorter=
term (the impact on the standard is small enough that reasoning about it i=
s simple and, I think we can agree, safe). But at the same time it is the m=
ost expensive alternative of the three for developers, and not trivial to u=
se (not only for the library implementor, but also for the implementor of t=
he relocatable types).
>=20
> If the other approaches hit a wall and cannot proceed, David's approach i=
s better than nothing, but I'd rather get something less intrusive on user =
code.
My approach isn=E2=80=99t primarily motivated by minimizing the changes to =
the standard, it=E2=80=99s for correctness and generality.
I need to think about how aggregates can be accommodated (without any user =
intervention, not even a trait), and whether that extension is sufficient.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_05DA5FBC-086C-48BC-980D-F66B363CAE2B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"><meta http-equiv=3D"Content-Type" content=3D"text/html charset=3D=
utf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: spac=
e; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><div c=
lass=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=
=80=9308=E2=80=9303, at 4:56 PM, David Rodr=C3=ADguez Ibeas <<a href=3D"=
mailto:dibeas@ieee.org" class=3D"">dibeas@ieee.org</a>> wrote:</div><br =
class=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=
=3D"">There's a couple of things I dislike of David Krauss' proposal, while=
I understand that it is an attempt to make something work in a much simple=
r way than the alternatives in the language.<br class=3D""></div></div></bl=
ockquote><div class=3D""><br class=3D""></div><div class=3D"">The prioritie=
s are:</div><div class=3D""><br class=3D""></div><div class=3D"">1. Correct=
ness. Generating wrong programs is taking a step backward.</div><div class=
=3D"">2. Efficiency and generality. There are two dimensions of generalizat=
ion: handling nontrivial move-and-destroy, and handling composition.</div><=
div class=3D"">3. Ease of use. =E2=80=9CSimplicity=E2=80=9D isn=E2=80=99t g=
enuine if you need to work through details of the object model, such as man=
ually computing <font face=3D"Courier" class=3D"">is_pod</font>.</div><br c=
lass=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"=
ltr" class=3D"">I dislike forcing the design of the types into a base with =
members and a derived type with functionality on purely theoretical grounds=
(was this the only concern I may swallow those), but in forcing a particul=
ar layout of the members and code I feel it inhibits non-trivial uses. I do=
n't see, for example, how composibility could be obtained. In the libraries=
that offer relocability through traits this is easily handled in BSL:<br c=
lass=3D""></div></div></blockquote><div class=3D""><br class=3D""></div><di=
v class=3D"">Yeah, composition seems to merit support.</div><div class=3D""=
><br class=3D""></div><div class=3D"">Requiring the user to factor out the =
base is a positive aspect. If they don=E2=80=99t, the compiler still has to=
do something very similar behind the scenes. What gets initialized by <fon=
t face=3D"Courier" class=3D"">__COOKIE__</font>? A layout-compatible but tr=
ivially constructible class that hasn=E2=80=99t been declared. The language=
works better when all the cards are on the table.</div><div class=3D""><br=
class=3D""></div><div class=3D"">Factoring out a base class is pretty elem=
entary. What=E2=80=99s the theoretical objection? Don=E2=80=99t like to dec=
lare classes that aren=E2=80=99t part of the public interface? That=E2=80=
=99s a general impediment to good OO design. Remember that this is a perfor=
mance optimization. That alone puts aesthetics at risk, and something=E2=80=
=99s gotta give: The alternative is to open <font face=3D"Courier" class=3D=
"">namespace std</font> for the sake of adding a manual specialization.</di=
v><div class=3D""><br class=3D""></div><div class=3D"">There is one thing t=
hat can break when factoring a base. The type of address-of-member expressi=
ons <font face=3D"Courier" class=3D"">&foo::mem</font> becomes <font fa=
ce=3D"Courier" class=3D"">mem_t base::*</font>, which doesn=E2=80=99t impli=
citly convert back to the original type <span style=3D"font-family: Co=
urier;" class=3D"">mem_t derived::*</span>. Perhaps this should be revisite=
d; AFAIK it=E2=80=99s only done that way for ease of implementation and it =
often causes headaches when using PTMs.</div><div class=3D""><br class=3D""=
></div><div class=3D"">Back to composition: If the base class is required t=
o be an aggregate, then it=E2=80=99s not too =E2=80=9Cdirty=E2=80=9D to let=
destructive move construction propagate down to its members. As for the me=
chanics of that, I=E2=80=99ll have to let this simmer on the back burner fo=
r a little while.</div><div class=3D""><br class=3D""></div><blockquote typ=
e=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div clas=
s=3D""><div class=3D"">I believe that from a user's point of view (more peo=
ple will develop code than the standard), the simplest approach is what cur=
rent libraries do: the user that creates a type need only provide the trait=
, the library does the rest of the work and that work is minimal at the lib=
rary level. Requiring that the movable type is split hierarchically in a pa=
rticular way forces a redesign on user types that I don't quite like.<br cl=
ass=3D""></div></div></div></div></blockquote><div class=3D""><br class=3D"=
"></div><div class=3D"">The trait is ugly and tricky to declare (sacrifice =
#3 ease) and tricky to specify (you need to remember to compose the types o=
f all the members, sacrifice #1 correctness). Doubly so for traits of templ=
ates. The trait only covers the trivial case, otherwise you need to reimple=
ment the destructive move algorithm (sacrifice #2 generality or double down=
on sacrifices of #1 and #3).</div><div class=3D""><br class=3D""></div><di=
v class=3D"">The established practice of libraries is a local optimum for m=
etaprogramming. Adding a feature to the core language should be a deeper pr=
ocess than internalizing a metaprogram.</div><br class=3D""><blockquote typ=
e=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div clas=
s=3D""><div class=3D"">David's approach here is the one that makes this ava=
ilable in the shorter term (the impact on the standard is small enough that=
reasoning about it is simple and, I think we can agree, safe). But at the =
same time it is the most expensive alternative of the three for developers,=
and not trivial to use (not only for the library implementor, but also for=
the implementor of the relocatable types).<br class=3D""><br class=3D"">If=
the other approaches hit a wall and cannot proceed, David's approach is be=
tter than nothing, but I'd rather get something less intrusive on user code=
..<br class=3D""></div></div></div></div></blockquote></div><br class=3D""><=
div class=3D"">My approach isn=E2=80=99t primarily motivated by minimizing =
the changes to the standard, it=E2=80=99s for correctness and generality.</=
div><div class=3D""><br class=3D""></div><div class=3D"">I need to think ab=
out how aggregates can be accommodated (without <i class=3D"">any</i> =
user intervention, not even a trait), and whether that extension is suffici=
ent.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_05DA5FBC-086C-48BC-980D-F66B363CAE2B--
.
Author: Pablo Halpern <phalpern@halpernwightsoftware.com>
Date: Tue, 04 Aug 2015 11:44:20 -0400
Raw View
Chandler and I have not connected yet on this topic. N4393 was not well=20
received at the last meeting and Chandler claimed to have better ideas,=20
but I have not learned from him what those ideas are. I'm afraid I lost=20
a bit of momentum since that meeting in not following up immediately=20
with Chandler. I will need to put that back on the front burner soon.
David, I'm afraid I don't understand your base-class destructor idea. =20
Possibly I missed the first part of the discussion. I will point out=20
that, for destructive move, the destructor is actually the easy part. =20
If I understand the language correctly, it is already valid to end the=20
lifetime of an object simply by reusing the memory. Therefore, a noop=20
destruction should be implementable this way:
template <class T>
void unbless(T& x) noexcept {
struct empty { };
empty *e =3D ::new (addressof(x)) empty;
e->~empty();
}
Taking a bunch of bytes and making a valid object out of them (noop=20
construction) is more challenging, so trivial destructive move=20
construction (using the equivalent of memcpy) is still problematic. =20
However, explicit destructive move could be implemented on a=20
class-by-class basis:
MyClass::MyClass(destructive_move_ref<MyClass> dr) noexcept
{
MyClass& r =3D dr.get_ref();
this->mem1 =3D dr.mem1;
this->mem2 =3D dr.mem2;
...
unbless(r);
}
If this is invoked in a tight loop, can the compiler's optimizer convert=20
it to a memcpy? If so, then perhaps the trivial variant isn't needed,=20
though it would be extremely convenient for a large category of types.
-Pablo
On 08/03/15 00:20, David Krauss wrote:
>> On 2015=E2=80=9308=E2=80=9303, at 3:18 AM, Ville Voutilainen <ville.vout=
ilainen@gmail.com> wrote:
>>
>> When it comes to destructive move, I want to see Pablo's follow-up, beca=
use he
>> and Chandler were tasked to look at whether the destructive moves the pr=
oposed
>> are truly necessary. If you think you have useful material for such a
>> follow-up, talk to him.
> Is N4393 not that followup?
>
> This is why I=E2=80=99m asking for feedback here (and CC=E2=80=99ing Pabl=
o). This proposal is not my baby, and it can be stopped in its tracks if so=
meone points out that something critical is missing. I=E2=80=99d prefer not=
to waste effort developing something that=E2=80=99s doomed.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 5 Aug 2015 13:03:52 +0800
Raw View
--Apple-Mail=_97FEDCC1-F4AA-439C-8DF8-9096B5ACCD5C
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9304, at 11:44 PM, Pablo Halpern <phalpern@halpe=
rnwightsoftware.com> wrote:
>=20
> David, I'm afraid I don't understand your base-class destructor idea. Po=
ssibly I missed the first part of the discussion. I will point out that, f=
or destructive move, the destructor is actually the easy part. If I unders=
tand the language correctly, it is already valid to end the lifetime of an =
object simply by reusing the memory. =20
Only for trivially destructible objects. As I understand the original conce=
rn, the problem is that a nontrivial destructor must be executed before con=
structing a new object at the same location. Otherwise it=E2=80=99s a runti=
me violation of the one-object-per-address rule [intro.object] =C2=A71.8/6.=
That rule is usually taken to constrain ABIs, but sanitizers may also rely=
on and/or check it. On the other hand, reviewing [basic.life] =C2=A73.8/1.=
3, this interpretation requires the final =E2=80=9Cor=E2=80=9D to be taken =
to mean =E2=80=9Cotherwise=E2=80=9D which isn=E2=80=99t really what it says=
..
Besides such a technicality, the user might really need a destructor call. =
I=E2=80=99ve used <https://code.google.com/p/c-plus/source/browse/src/strin=
g.h#92> nontrivially destructible fancy pointers to manage garbage collecti=
on. (Though structured a bit differently, that library should have been imp=
lementable as a custom allocator on std::string, but for the lack of a shri=
nk_to_fit hook.) Allocator objects likewise may retain a shared memory pool=
..
The normative permission to end an object=E2=80=99s lifetime without callin=
g its nontrivial destructor =C2=A73.8/4 has a stern warning about undefined=
behavior. The standard library should avoid skipping nontrivial destructor=
s.
> Therefore, a noop destruction should be implementable this way:
>=20
> template <class T>
> void unbless(T& x) noexcept {
> struct empty { };
> empty *e =3D ::new (addressof(x)) empty;
> e->~empty();
> }
~empty() should be unnecessary if ~T() is. Also, ~empty() is trivial so it =
can certainly be omitted. The new-expression fails to begin the lifetime of=
*e because it is vacuous per =C2=A73.8/1.
This should be sufficient (though I=E2=80=99m not recommending it):
struct empty { empty() {} };
template <class T>
void unbless(T& x) noexcept {
new (addressof(x)) empty;
}
> If this is invoked in a tight loop, can the compiler's optimizer convert =
it to a memcpy? If so, then perhaps the trivial variant isn't needed,
Yeah, that=E2=80=99s my thinking.
> though it would be extremely convenient for a large category of types.
Even more convenient would be getting an an implicit definition to do it fo=
r you, regardless of triviality. But, that sticks something like destructiv=
e_move_ref into the core language.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_97FEDCC1-F4AA-439C-8DF8-9096B5ACCD5C
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=
=E2=80=9304, at 11:44 PM, Pablo Halpern <<a href=3D"mailto:phalpern@halp=
ernwightsoftware.com" class=3D"">phalpern@halpernwightsoftware.com</a>> =
wrote:</div><div class=3D""><br class=3D"">David, I'm afraid I don't unders=
tand your base-class destructor idea. Possibly I missed the first par=
t of the discussion. I will point out that, for destructive move, the=
destructor is actually the easy part. If I understand the language c=
orrectly, it is already valid to end the lifetime of an object simply by re=
using the memory. </div></blockquote><div><br class=3D""></div><div>O=
nly for trivially destructible objects. As I understand the original concer=
n, the problem is that a nontrivial destructor must be executed before cons=
tructing a new object at the same location. Otherwise it=E2=80=99s a runtim=
e violation of the one-object-per-address rule [intro.object] =C2=A71.8/6. =
That rule is usually taken to constrain ABIs, but sanitizers may also rely =
on and/or check it. On the other hand, reviewing [basic.life] =C2=A73.8/1.3=
, this interpretation requires the final =E2=80=9Cor=E2=80=9D to be taken t=
o mean =E2=80=9Cotherwise=E2=80=9D which isn=E2=80=99t really what it says.=
</div><div><br class=3D""></div><div>Besides such a technicality, the user =
might really need a destructor call. I=E2=80=99ve <a href=3D"https://c=
ode.google.com/p/c-plus/source/browse/src/string.h#92" class=3D"">used</a>&=
nbsp;nontrivially destructible fancy pointers to manage garbage collection.=
(Though structured a bit differently, that library should have been implem=
entable as a custom allocator on <font face=3D"Courier" class=3D"">std::str=
ing</font>, but for the lack of a <font face=3D"Courier" class=3D"">shrink_=
to_fit</font> hook.) Allocator objects likewise may retain a shared memory =
pool.</div><div><br class=3D""></div><div>The normative permission to end a=
n object=E2=80=99s lifetime without calling its nontrivial destructor =C2=
=A73.8/4 has a stern warning about undefined behavior. The standard library=
should avoid skipping nontrivial destructors.</div><br class=3D""><blockqu=
ote type=3D"cite" class=3D""><div class=3D"">Therefore, a noop destruction =
should be implementable this way:<br class=3D""><br class=3D"">template <=
;class T><br class=3D"">void unbless(T& x) noexcept {<br class=3D"">=
struct empty { };<br class=3D""> empty=
*e =3D ::new (addressof(x)) empty;<br class=3D""> e->=
~empty();<br class=3D"">}<br class=3D""></div></blockquote><div><br class=
=3D""></div><div><font face=3D"Courier" class=3D"">~empty()</font> should b=
e unnecessary if <font face=3D"Courier" class=3D"">~T()</font> is=
.. Also, <font face=3D"Courier" class=3D"">~empty()</font> is trivial so it =
can certainly be omitted. The new-expression fails to begin the lifetime of=
<font face=3D"Courier" class=3D"">*e</font> because it is vacuous per =C2=
=A73.8/1.</div><div><br class=3D""></div><div>This should be sufficient (th=
ough I=E2=80=99m not recommending it):</div><div><br class=3D""></div><font=
face=3D"Courier" class=3D"">struct empty { empty() {} };<br class=3D""></f=
ont><div><font face=3D"Courier" class=3D""><br class=3D""></font></div><div=
><font face=3D"Courier" class=3D"">template <class T><br class=3D"">v=
oid unbless(T& x) noexcept {<br class=3D""> new (addressof(=
x)) empty;<br class=3D"">}</font></div><div><br class=3D""></div><blockquot=
e type=3D"cite" class=3D""><div class=3D"">If this is invoked in a tight lo=
op, can the compiler's optimizer convert it to a memcpy? If so, then =
perhaps the trivial variant isn't needed, </div></blockquote><div><br class=
=3D""></div><div><div><div>Yeah, that=E2=80=99s my thinking.</div></div><br=
class=3D""></div><blockquote type=3D"cite" class=3D""><div class=3D"">thou=
gh it would be extremely convenient for a large category of types.<br class=
=3D""></div></blockquote><div><br class=3D""></div><div>Even more convenien=
t would be getting an an implicit definition to do it for you, regardless o=
f triviality. But, that sticks something like <font face=3D"Courier" class=
=3D"">destructive_move_ref</font> into the core language.</div></div><div c=
lass=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_97FEDCC1-F4AA-439C-8DF8-9096B5ACCD5C--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Wed, 5 Aug 2015 10:40:59 +0100
Raw View
--001a11c264be439fae051c8d33d4
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Aug 5, 2015 at 6:03 AM, David Krauss <potswa@gmail.com> wrote:
>
> The normative permission to end an object=E2=80=99s lifetime without call=
ing its
> nontrivial destructor =C2=A73.8/4 has a stern warning about undefined beh=
avior.
> The standard library should avoid skipping nontrivial destructors.
>
The warning in 3.8/4 would not apply to a type that has been marked as
destructive-movable as marking it as such would be the programmer's
blessing that it is fine (and even desirable) to skip the destructor, that
it is fine and desirable for the program not to have the side effects of
the destructor when used in a destructive move operation.
> Even more convenient would be getting an an implicit definition to do it
> for you, regardless of triviality. But, that sticks something like
> destructive_move_ref into the core language.
>
Having a 'destructive_move_ref' in the core language could also allow for
alternative implementations of destructive-move-constructor where a self
referencing type could overload an specific constructor/destructor to do
something like memcpy + patching of references. For example, in the case of
a string doing RVO and holding a possibly self-referencing pointer it could
do a memcpy of the string object and conditionally adjust the pointer to
the internal buffer if it is using the small buffer. Then again, at this
time it would (guessing) not be more efficient than the equivalent
move-constructor.
On a wicked attempt at bike-shedding the operation, we could add a
move-destructor:
template <typename T, typename A =3D std::allocator<T> >
class list {
// Imagine this as Dinkumware's implementation of 'std::list', assume
SFINAE for a destructive-movable allocator
Node *sentry; // for exposition
list(list&& src) noexcept(false);
~list(void *dst) noexcept(true) { // ~list([[uninitialized]] list *dst)
memcpy(dst, this, sizeof *this);
}
With that move-destructor being blessed by the standard as both terminating
the lifetime of 'this' and creating a new object over 'dst', behaviorally
equivalent, with respect to lifetimes, to:
new (dst) list(std::move(*this));
this->~list();
The optimizer would have to figure out, does not seem too complicated, that
multiple memcpy's for contiguous memory can be coalesced into a single
memcpy/memmove. The 'memmove' is because while the move-destructor cannot
be called (documented as undefined behavior) with 'dst =3D=3D this', a loop=
of
move-destructor's may be shifting elements in overlapping regions in a
vector.
The move-destructor would not be implicitly declared, but could be
defaulted to just do the memcpy, so implementors can just do:
~list(void *dst) =3D default;
which would at the same time be detectable by a 'is_move_destructible<T>',
the real change to 'std::list' in such implementations would be:
template <typename T, typename A =3D allocator<T>>
class list {
// ...
template <typename U =3D A, typename _ =3D typename
enable_if<is_move_destructible<A<T>>::type>
~list(void *dst) =3D default
Which is a bit obscure, but not too horrible for a library implementation.
(I feel that the argument being 'list *dst' would be nicer for the
developer, but I am not sure about passing a pointer to a memory location
that is not a 'T' as a 'T*', if that is fine I'd prefer to have the
argument typed).
David
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c264be439fae051c8d33d4
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Aug 5, 2015 at 6:03 AM, David Krauss <span dir=3D"ltr"><<a h=
ref=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.com</a>><=
/span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:bre=
ak-word"><div><div><br></div><div>The normative permission to end an object=
=E2=80=99s lifetime without calling its nontrivial destructor =C2=A73.8/4 h=
as a stern warning about undefined behavior. The standard library should av=
oid skipping nontrivial destructors.</div></div></div></blockquote><div><br=
>The warning in 3.8/4 would not apply to a type that has been marked as des=
tructive-movable as marking it as such would be the programmer's blessi=
ng that it is fine (and even desirable) to skip the destructor, that it is =
fine and desirable for the program not to have the side effects of the dest=
ructor when used in a destructive move operation.<br>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div style=3D"word-wrap:break-word"><div><span class=
=3D""><div>Even more convenient would be getting an an implicit definition =
to do it for you, regardless of triviality. But, that sticks something like=
<font face=3D"Courier">destructive_move_ref</font> into the core language.=
</div></span></div></div></blockquote><div><br></div><div>=C2=A0Having a &#=
39;destructive_move_ref' in the core language could also allow for alte=
rnative implementations of destructive-move-constructor where a self refere=
ncing type could overload an specific constructor/destructor to do somethin=
g like memcpy + patching of references. For example, in the case of a strin=
g doing RVO and holding a possibly self-referencing pointer it could do a m=
emcpy of the string object and conditionally adjust the pointer to the inte=
rnal buffer if it is using the small buffer.=C2=A0 Then again, at this time=
it would (guessing) not be more efficient than the equivalent move-constru=
ctor.<br><br>On a wicked attempt at bike-shedding the operation, we could a=
dd a move-destructor:<br><br>template <typename T, typename A =3D std::a=
llocator<T> ><br>class list {<br>=C2=A0 =C2=A0// Imagine this as D=
inkumware's implementation of 'std::list', assume SFINAE for a =
destructive-movable allocator<br>=C2=A0 =C2=A0Node *sentry; =C2=A0// for ex=
position<br><br>=C2=A0 =C2=A0list(list&& src) noexcept(false);<br>=
=C2=A0 =C2=A0~list(void *dst) noexcept(true) { // ~list([[uninitialized]] l=
ist *dst)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0memcpy(dst, this, sizeof *this);</d=
iv><div>=C2=A0 =C2=A0}<br><br>With that move-destructor being blessed by th=
e standard as both terminating the lifetime of 'this' and creating =
a new object over 'dst', behaviorally equivalent, with respect to l=
ifetimes, to:<br><br>new (dst) list(std::move(*this));<br>this->~list();=
<br><br>The optimizer would have to figure out, does not seem too complicat=
ed, that multiple memcpy's for contiguous memory can be coalesced into =
a single memcpy/memmove.=C2=A0 The 'memmove' is because while the m=
ove-destructor cannot be called (documented as undefined behavior) with =
9;dst =3D=3D this', a loop of move-destructor's may be shifting ele=
ments in overlapping regions in a vector.<br><br>The move-destructor would =
not be implicitly declared, but could be defaulted to just do the memcpy, s=
o implementors can just do:<br><br>~list(void *dst) =3D default;<br><br>whi=
ch would at the same time be detectable by a 'is_move_destructible<T=
>', the real change to 'std::list' in such implementations w=
ould be:<br><br>template <typename T, typename A =3D allocator<T>&=
gt;<br>class list {<br>// ...<br>=C2=A0 =C2=A0 template <typename U =3D =
A, typename _ =3D typename enable_if<is_move_destructible<A<T>&=
gt;::type><br>=C2=A0 =C2=A0 ~list(void *dst) =3D default<br><br>Which is=
a bit obscure, but not too horrible for a library implementation. (I feel =
that the argument being 'list *dst' would be nicer for the develope=
r, but I am not sure about passing a pointer to a memory location that is n=
ot a 'T' as a 'T*', if that is fine I'd prefer to have =
the argument typed).<br><br>=C2=A0 =C2=A0 David</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c264be439fae051c8d33d4--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Wed, 5 Aug 2015 10:43:01 +0100
Raw View
--001a11c264be83976a051c8d3a89
Content-Type: text/plain; charset=UTF-8
Ouch, let me fix that declaration:
template <typename T, typename A = allocator<T>>
> class list {
> // ...
> template <typename U = A, typename _ = typename
> enable_if<is_move_destructible<U>>::type>
> ~list(void *dst) = default
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c264be83976a051c8d3a89
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Ouch, let me fix that declaration:<div class=3D"gmail_extr=
a"><br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">template <=
;typename T, typename A =3D allocator<T>><br>class list {<br>// ..=
..<br>=C2=A0 =C2=A0 template <typename U =3D A, typename _ =3D typename e=
nable_if<is_move_destructible<U>>::type><br>=C2=A0 =C2=A0 ~l=
ist(void *dst) =3D default<br></div></div></div>
</blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c264be83976a051c8d3a89--
.
Author: =?UTF-8?Q?Ion_Gazta=c3=b1aga?= <igaztanaga@gmail.com>
Date: Thu, 6 Aug 2015 01:18:08 +0200
Raw View
El 05/08/2015 a las 7:03, David Krauss escribi=C3=B3:
> Only for trivially destructible objects. As I understand the original
> concern, the problem is that a nontrivial destructor must be executed
> before constructing a new object at the same location. Otherwise it=E2=80=
=99s a
> runtime violation of the one-object-per-address rule [intro.object]
> =C2=A71.8/6. That rule is usually taken to constrain ABIs, but sanitizers=
may
> also rely on and/or check it. On the other hand, reviewing [basic.life]
> =C2=A73.8/1.3, this interpretation requires the final =E2=80=9Cor=E2=80=
=9D to be taken to
> mean =E2=80=9Cotherwise=E2=80=9D which isn=E2=80=99t really what it says.
Sorry for jumping in the middle of the discussion, I don't think the=20
standard requires calling the destructor at all. The standard states=20
that the lifetime of an object ends when the storage is reused:
"4 A program may end the lifetime of any object by reusing the storage=20
which the object occupies or by explicitly calling the destructor for an=20
object of a class type with a non-trivial destructor. For an object of a=20
class type with a non-trivial destructor, the program is not required to=20
call the destructor explicitly before the storage which the object=20
occupies is reused or released; however, if there is no explicit call to=20
the destructor or if a delete-expression (5.3.5) is not used to release=20
the storage, the destructor shall not be implicitly called and any=20
program that depends on the side effects produced by the destructor has=20
undefined behavior."
So not calling the destructor is not UB, it's UB if any other code=20
depends on the work the destructor does (that is, the destructor frees=20
resources to avoid leaks or blocked resources, the destructor=20
communicates with other classes or observers that always need to track=20
when the object is being destroyed because external objects track the=20
address of the object to be destroyed, ...). In any case, the writer of=20
the destructive move operation can take care of such side-effects the=20
same way as the destructor does.
IMHO, destructive move semantics are allowed by current C++ rules, it=20
needs a constructor (which is required to start the lifetime of an=20
object) for destructive move construction and a plain function for the=20
destructive move assignment. I don't think any special rule or cookie=20
constructor/destructor is absolutely needed. Maybe those special=20
constructors/destructors could help the compiler to do a better job.=20
memcpy-ing for destructive move constructors is another issue, but=20
related to the start of the lifetime of the new objects.
Just my 2 cents,
Best,
Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Pablo Halpern <phalpern@halpernwightsoftware.com>
Date: Wed, 05 Aug 2015 20:34:43 -0400
Raw View
Thanks, Ion. That is my understanding as well. One question that=20
doesn't seem to be answered: can you end the lifetime of an object by=20
deallocating its storage (again, without using a delete expression). If=20
so, then there is no need for the trick I used in overwriting the object=20
with an empty class type.
-Pablo
On 8/5/2015 7:18 PM, Ion Gazta=C3=B1aga wrote:
> El 05/08/2015 a las 7:03, David Krauss escribi=C3=B3:
>> Only for trivially destructible objects. As I understand the original
>> concern, the problem is that a nontrivial destructor must be executed
>> before constructing a new object at the same location. Otherwise it=E2=
=80=99s a
>> runtime violation of the one-object-per-address rule [intro.object]
>> =C2=A71.8/6. That rule is usually taken to constrain ABIs, but sanitizer=
s may
>> also rely on and/or check it. On the other hand, reviewing [basic.life]
>> =C2=A73.8/1.3, this interpretation requires the final =E2=80=9Cor=E2=80=
=9D to be taken to
>> mean =E2=80=9Cotherwise=E2=80=9D which isn=E2=80=99t really what it says=
..
>
> Sorry for jumping in the middle of the discussion, I don't think the=20
> standard requires calling the destructor at all. The standard states=20
> that the lifetime of an object ends when the storage is reused:
>
> "4 A program may end the lifetime of any object by reusing the storage=20
> which the object occupies or by explicitly calling the destructor for=20
> an object of a class type with a non-trivial destructor. For an object=20
> of a class type with a non-trivial destructor, the program is not=20
> required to call the destructor explicitly before the storage which=20
> the object occupies is reused or released; however, if there is no=20
> explicit call to the destructor or if a delete-expression (5.3.5) is=20
> not used to release the storage, the destructor shall not be=20
> implicitly called and any program that depends on the side effects=20
> produced by the destructor has undefined behavior."
>
> So not calling the destructor is not UB, it's UB if any other code=20
> depends on the work the destructor does (that is, the destructor frees=20
> resources to avoid leaks or blocked resources, the destructor=20
> communicates with other classes or observers that always need to track=20
> when the object is being destroyed because external objects track the=20
> address of the object to be destroyed, ...). In any case, the writer=20
> of the destructive move operation can take care of such side-effects=20
> the same way as the destructor does.
>
> IMHO, destructive move semantics are allowed by current C++ rules, it=20
> needs a constructor (which is required to start the lifetime of an=20
> object) for destructive move construction and a plain function for the=20
> destructive move assignment. I don't think any special rule or cookie=20
> constructor/destructor is absolutely needed. Maybe those special=20
> constructors/destructors could help the compiler to do a better job.=20
> memcpy-ing for destructive move constructors is another issue, but=20
> related to the start of the lifetime of the new objects.
>
> Just my 2 cents,
>
> Best,
>
> Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Ion_Gazta=c3=b1aga?= <igaztanaga@gmail.com>
Date: Thu, 6 Aug 2015 07:12:59 +0200
Raw View
El 06/08/2015 a las 2:34, Pablo Halpern escribi=C3=B3:
> Thanks, Ion. That is my understanding as well. One question that
> doesn't seem to be answered: can you end the lifetime of an object by
> deallocating its storage (again, without using a delete expression). If
> so, then there is no need for the trick I used in overwriting the object
> with an empty class type.
According to the standard, you can (3.8 Object lifetime):
The lifetime of an object of type T ends when:
(1.3) =E2=80=94 if T is a class type with a non-trivial destructor (12.4), =
the=20
destructor call starts, or
(1.4) =E2=80=94 the storage which the object occupies is reused or *RELEASE=
D*
I understand that 1.4 applies also to types with non-trivial destructors.
So you can:
- release that memory (but this is outside the scope of the destructive=20
move operation)
- explicitly "reuse" memory
- just wait until it's reused someday, as the side effects are already=20
committed by the destructive move operation. Whether the lifetime of the=20
original object was destroyed or not it's irrelevant for the rest of the=20
program, as no additional side effects related to that object will be=20
visible once the destructive move ends. This could make some sanitizers=20
work harder, who knows.
The trick with the empty class (or just using a "char", might be enough,=20
so the alignment is always guaranteed) would "end" the lifetime of the=20
original object before the destructive move operation ends. I don't know=20
if the compiler will be happier with this "explicit" lifetime end, I=20
suspect just waiting the memory to be reused (my the memory=20
allocator/stack handling or a placement new/memcpy) or released (maybe=20
at program exit) will be fine.
Just a note: since "empty" has a trivial destructor, then this:
e->~empty();
would not end the lifetime of the object as (1.3) applies only to types=20
with non-trivial destructors ;-).
IMHO it's an oversight, bullet 1.3 should read:
(1.3) =E2=80=94 the destructor invocation starts, or
(1.4) =E2=80=94 the storage which the object occupies is reused or released
You could define an inline empty destructor in empty to "guarantee"=20
current (1.3) wording.
Best,
Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Thu, 6 Aug 2015 09:35:05 +0100
Raw View
--001a113495b27153ac051ca065cc
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I wasn't as much concerned with the destruction as the construction. The
question comes back again as of whether a compiler could be smart enough to
merge multiple 'memcpy', and while in the trivial case it would seem
reasonable, I fear the are some cases that are not so trivial in the
presence of padding, for example.
Additionally, my understanding --we need measurements here, I had not had
the time to test this-- is that a big part of the gain would be blasting
contiguous objects with a single call to 'memcpy' or 'memmove'. For the
example of a vector that needs to grow the internal buffer a compiler
merging the 'memcpy' for the destructive-move-constructor suffices. But
there are other operations like insert in the middle of a vector (assume
capacity is enough for the insertion) where an implementation could do
something like:
vector<T>::insert_impl(iterator pos, T&& value, destructive_move_tag)
// picked by tag-dispatch for destructive-movable types T
{
// Create the object into a local buffer:
alignas(T) char buffer[sizeof value];
new (buffer) T(move(value));
// From here on nothing can throw
for (iterator e =3D __end; e > pos; --e) {
new (addressof(*e)) T(destructive_move_tag, e-1); // internally
'memcpy'
}
new (addressof(*pos)) T(destructive_move_tag,
reinterpret_cast<T*>(buffer));
++__end;
}
And hope that the compiler transforms that into:
=E2=80=A6 // From here on nothing can throw
memmove(addressof(*pos)+1, addressof(*pos), (__end-pos) * sizeof(T));
// not memcpy!!
memcpy(addressof(*pos), reinterpret_cast<T*>(buffer), sizeof(T));
++__end;
}
At the same time, this depends on the destructive-move constructor being
visible at all to the compiler (either it is inline, or it whole-program
optimization somehow detected and decided to re-inline the function.
Beyond the implementation details, users must provide the destructive-move
constructors (I am fine, this is a dangerous thing to do, be conscious!)
and the implementation of that function has to be palatable for the
optimizer to do the transformation.
Again, padding might have a negative effect here, consider a non-empty
comparator in std::set that is destructive-movable. Consider also that the
size of such object is smaller than the natural alignment for the platform,
so that there is internal padding inside std::set<T> between the comparator
and the other members. The implementation cannot just "blast" the
comparator if, being user provided, it may do something other than memcpy.
It would have to call the destructive-move on the comparator and then blast
the rest of the members, generating a destructive-move constructor with 3
memcpy (allocator, comparator, rest of the members), yet those memcpy are
not contiguous due to internal padding.
Whether an implementation is allowed to detect that moving the padding
around is not problematic and can be merged or not determines whether a
vector<set<T>> can do a single 'memcpy' to grow the buffer or needs to loop
over each one of the elements and run the constructor one by one.
To some extents these are concerns more on the feasibility of the
implementation (optimizer) than the language itself, and it can be argued
that if a tag for the constructor, a wrapper ('destructive_move_ref<T>()')
or any other mechanism is standardized, compiler writers would have an
incentive to work towards providing these optimizations.
Yet another concern is that the source object is left in an invalid state,
which opens the path for misuse, for example the implementation of
'insert_impl' above could be attempted by a non-expert user as:
vector<T>::insert_impl(iterator pos, T&& value, destructive_move_tag)
T tmp(move(value));
=E2=80=A6
And at the end of the function when the destructor runs you are likely to
hit undefined behavior as the object is invalid. Worse, the 'tmp' could be
omitted altogether and the last line transformed into:
new (addressof(*pos)) T(destructive_move_tag, value); // reference to
externally managed object
David
On Thu, Aug 6, 2015 at 6:12 AM, Ion Gazta=C3=B1aga <igaztanaga@gmail.com> w=
rote:
> El 06/08/2015 a las 2:34, Pablo Halpern escribi=C3=B3:
>
>> Thanks, Ion. That is my understanding as well. One question that
>> doesn't seem to be answered: can you end the lifetime of an object by
>> deallocating its storage (again, without using a delete expression). If
>> so, then there is no need for the trick I used in overwriting the object
>> with an empty class type.
>>
>
> According to the standard, you can (3.8 Object lifetime):
>
> The lifetime of an object of type T ends when:
> (1.3) =E2=80=94 if T is a class type with a non-trivial destructor (12.4)=
, the
> destructor call starts, or
> (1.4) =E2=80=94 the storage which the object occupies is reused or *RELEA=
SED*
>
> I understand that 1.4 applies also to types with non-trivial destructors.
>
> So you can:
> - release that memory (but this is outside the scope of the destructive
> move operation)
> - explicitly "reuse" memory
> - just wait until it's reused someday, as the side effects are already
> committed by the destructive move operation. Whether the lifetime of the
> original object was destroyed or not it's irrelevant for the rest of the
> program, as no additional side effects related to that object will be
> visible once the destructive move ends. This could make some sanitizers
> work harder, who knows.
>
> The trick with the empty class (or just using a "char", might be enough,
> so the alignment is always guaranteed) would "end" the lifetime of the
> original object before the destructive move operation ends. I don't know =
if
> the compiler will be happier with this "explicit" lifetime end, I suspect
> just waiting the memory to be reused (my the memory allocator/stack
> handling or a placement new/memcpy) or released (maybe at program exit)
> will be fine.
>
> Just a note: since "empty" has a trivial destructor, then this:
>
> e->~empty();
>
> would not end the lifetime of the object as (1.3) applies only to types
> with non-trivial destructors ;-).
>
> IMHO it's an oversight, bullet 1.3 should read:
>
> (1.3) =E2=80=94 the destructor invocation starts, or
> (1.4) =E2=80=94 the storage which the object occupies is reused or releas=
ed
>
> You could define an inline empty destructor in empty to "guarantee"
> current (1.3) wording.
>
>
> Best,
>
> Ion
>
> --
>
> --- You received this message because you are subscribed to the Google
> Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a113495b27153ac051ca065cc
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I wasn't as much concerned with the destruction as the=
construction. The question comes back again as of whether a compiler could=
be smart enough to merge multiple 'memcpy', and while in the trivi=
al case it would seem reasonable, I fear the are some cases that are not so=
trivial in the presence of padding, for example.<div><br></div><div>Additi=
onally, my understanding --we need measurements here, I had not had the tim=
e to test this-- is that a big part of the gain would be blasting contiguou=
s objects with a single call to 'memcpy' or 'memmove'. For =
the example of a vector that needs to grow the internal buffer a compiler m=
erging the 'memcpy' for the destructive-move-constructor suffices. =
But there are other operations like insert in the middle of a vector (assum=
e capacity is enough for the insertion) where an implementation could do so=
mething like:</div><div><br></div><div>vector<T>::insert_impl(iterato=
r pos, T&& value, destructive_move_tag)=C2=A0</div><div>=C2=A0 =C2=
=A0 // picked by tag-dispatch for destructive-movable types T</div><div>{</=
div><div>=C2=A0 =C2=A0 // Create the object into a local buffer:</div><div>=
=C2=A0 =C2=A0 alignas(T) char buffer[sizeof value];</div><div>=C2=A0 =C2=A0=
new (buffer) T(move(value));</div><div><br></div><div>=C2=A0 =C2=A0 // Fro=
m here on nothing can throw</div><div>=C2=A0 =C2=A0 for (iterator e =3D __e=
nd; e > pos; --e) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 new (addressof=
(*e)) T(destructive_move_tag, e-1); =C2=A0// internally 'memcpy'</d=
iv><div>=C2=A0 =C2=A0 }</div><div>=C2=A0 =C2=A0 new (addressof(*pos)) T(des=
tructive_move_tag, reinterpret_cast<T*>(buffer));</div><div>=C2=A0 =
=C2=A0 ++__end;</div><div>}</div><div><br></div><div>And hope that the comp=
iler transforms that into:</div><div><br></div><div>=E2=80=A6 =C2=A0// From=
here on nothing can throw</div><div>=C2=A0 =C2=A0 =C2=A0memmove(addressof(=
*pos)+1, addressof(*pos), (__end-pos) * sizeof(T)); =C2=A0// not memcpy!!</=
div><div>=C2=A0 =C2=A0 =C2=A0memcpy(addressof(*pos), reinterpret_cast<T*=
>(buffer), sizeof(T));</div><div>=C2=A0 =C2=A0 =C2=A0++__end;</div><div>=
}</div><div><br></div><div>At the same time, this depends on the destructiv=
e-move constructor being visible at all to the compiler (either it is inlin=
e, or it whole-program optimization somehow detected and decided to re-inli=
ne the function.</div><div><br></div><div>Beyond the implementation details=
, users must provide the destructive-move constructors (I am fine, this is =
a dangerous thing to do, be conscious!) and the implementation of that func=
tion has to be palatable for the optimizer to do the transformation.</div><=
div><br></div><div>Again, padding might have a negative effect here, consid=
er a non-empty comparator in std::set that is destructive-movable. Consider=
also that the size of such object is smaller than the natural alignment fo=
r the platform, so that there is internal padding inside std::set<T> =
between the comparator and the other members. The implementation cannot jus=
t "blast" the comparator if, being user provided, it may do somet=
hing other than memcpy.=C2=A0 It would have to call the destructive-move on=
the comparator and then blast the rest of the members, generating a destru=
ctive-move constructor with 3 memcpy (allocator, comparator, rest of the me=
mbers), yet those memcpy are not contiguous due to internal padding. =C2=A0=
</div><div><br></div><div>Whether an implementation is allowed to detect th=
at moving the padding around is not problematic and can be merged or not de=
termines whether a vector<set<T>> can do a single 'memcpy&#=
39; to grow the buffer or needs to loop over each one of the elements and r=
un the constructor one by one.</div><div><br></div><div>To some extents the=
se are concerns more on the feasibility of the implementation (optimizer) t=
han the language itself, and it can be argued that if a tag for the constru=
ctor, a wrapper ('destructive_move_ref<T>()') or any other me=
chanism is standardized, compiler writers would have an incentive to work t=
owards providing these optimizations.</div><div><br></div><div>Yet another =
concern is that the source object is left in an invalid state, which opens =
the path for misuse, for example the implementation of 'insert_impl'=
; above could be attempted by a non-expert user as:</div><div><br></div><di=
v>vector<T>::insert_impl(iterator pos, T&& value, destructive=
_move_tag)=C2=A0<br></div><div>=C2=A0 =C2=A0T tmp(move(value));</div><div>=
=C2=A0 =C2=A0=E2=80=A6</div><div><br></div><div>And at the end of the funct=
ion when the destructor runs you are likely to hit undefined behavior as th=
e object is invalid.=C2=A0 Worse, the 'tmp' could be omitted altoge=
ther and the last line transformed into:</div><div><br></div><div>=C2=A0 =
=C2=A0 =C2=A0new (addressof(*pos)) T(destructive_move_tag, value); // refer=
ence to externally managed object</div><div><br></div><div><br></div><div>=
=C2=A0 =C2=A0 David<br></div></div><div class=3D"gmail_extra"><br><div clas=
s=3D"gmail_quote">On Thu, Aug 6, 2015 at 6:12 AM, Ion Gazta=C3=B1aga <span =
dir=3D"ltr"><<a href=3D"mailto:igaztanaga@gmail.com" target=3D"_blank">i=
gaztanaga@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"=
><span class=3D"">El 06/08/2015 a las 2:34, Pablo Halpern escribi=C3=B3:<br=
>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Thanks, Ion.=C2=A0 That is my understanding as well. One question that<br>
doesn't seem to be answered: can you end the lifetime of an object by<b=
r>
deallocating its storage (again, without using a delete expression).=C2=A0 =
If<br>
so, then there is no need for the trick I used in overwriting the object<br=
>
with an empty class type.<br>
</blockquote>
<br></span>
According to the standard, you can (3.8 Object lifetime):<br>
<br>
The lifetime of an object of type T ends when:<br>
(1.3) =E2=80=94 if T is a class type with a non-trivial destructor (12.4), =
the destructor call starts, or<br>
(1.4) =E2=80=94 the storage which the object occupies is reused or *RELEASE=
D*<br>
<br>
I understand that 1.4 applies also to types with non-trivial destructors.<b=
r>
<br>
So you can:<br>
- release that memory (but this is outside the scope of the destructive mov=
e operation)<br>
- explicitly "reuse" memory<br>
- just wait until it's reused someday, as the side effects are already =
committed by the destructive move operation. Whether the lifetime of the or=
iginal object was destroyed or not it's irrelevant for the rest of the =
program, as no additional side effects related to that object will be visib=
le once the destructive move ends. This could make some sanitizers work har=
der, who knows.<br>
<br>
The trick with the empty class (or just using a "char", might be =
enough, so the alignment is always guaranteed) would "end" the li=
fetime of the original object before the destructive move operation ends. I=
don't know if the compiler will be happier with this "explicit&qu=
ot; lifetime end, I suspect just waiting the memory to be reused (my the me=
mory allocator/stack handling or a placement new/memcpy) or released (maybe=
at program exit) will be fine.<br>
<br>
Just a note: since "empty" has a trivial destructor, then this:<b=
r>
<br>
=C2=A0 =C2=A0 e->~empty();<br>
<br>
would not end the lifetime of the object as (1.3) applies only to types wit=
h non-trivial destructors ;-).<br>
<br>
IMHO it's an oversight, bullet 1.3 should read:<br>
<br>
(1.3) =E2=80=94 the destructor invocation starts, or<br>
(1.4) =E2=80=94 the storage which the object occupies is reused or released=
<br>
<br>
You could define an inline empty destructor in empty to "guarantee&quo=
t; current (1.3) wording.<div class=3D"HOEnZb"><div class=3D"h5"><br>
<br>
Best,<br>
<br>
Ion<br>
<br>
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113495b27153ac051ca065cc--
.
Author: =?UTF-8?Q?Ion_Gazta=c3=b1aga?= <igaztanaga@gmail.com>
Date: Thu, 6 Aug 2015 12:43:58 +0200
Raw View
El 06/08/2015 a las 10:35, David Rodr=C3=ADguez Ibeas escribi=C3=B3:
> I wasn't as much concerned with the destruction as the construction. The
> question comes back again as of whether a compiler could be smart enough
> to merge multiple 'memcpy', and while in the trivial case it would seem
> reasonable, I fear the are some cases that are not so trivial in the
> presence of padding, for example.
I don't think the compiler will merge it, at least many compilers don't=20
optimize even simple loops into memcpy-s:
http://nadeausoftware.com/articles/2012/05/c_c_tip_how_copy_memory_quickly
A different issue is the direct use of memcpy for "is_relocatable"-like=20
types to implement highly optimized destructive move semantics. It's UB=20
even with N3751 which proposes that object lifetime starts with memcpy=20
for trivially copyable types:
http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3751.pdf
Of course in practice this kind of destructive move semantics work, as=20
used in BDE, Folly and other libraries:
https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md
"Only a tiny minority of objects are genuinely non-relocatable"
Supporting "trivially destructive movable" without UB is a much harder=20
work for the language.
Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 6 Aug 2015 12:04:11 +0100
Raw View
--001a11c33bb0a7372c051ca27a4b
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thu, Aug 6, 2015 at 11:43 AM, Ion Gazta=C3=B1aga <igaztanaga@gmail.com> =
wrote:
> El 06/08/2015 a las 10:35, David Rodr=C3=ADguez Ibeas escribi=C3=B3:
>
>> I wasn't as much concerned with the destruction as the construction. The
>> question comes back again as of whether a compiler could be smart enough
>> to merge multiple 'memcpy', and while in the trivial case it would seem
>> reasonable, I fear the are some cases that are not so trivial in the
>> presence of padding, for example.
>>
>
> I don't think the compiler will merge it, at least many compilers don't
> optimize even simple loops into memcpy-s:
>
> http://nadeausoftware.com/articles/2012/05/c_c_tip_how_copy_memory_quickl=
y
>
>
That's several years out of date; modern compilers (gcc 5; clang 3.7; icc)
have no problem ignoring padding and optimizing to memcpy. Example:
http://goo.gl/a0Xka7
Of course in practice this kind of destructive move semantics work, as used
> in BDE, Folly and other libraries:
>
> https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md
>
> "Only a tiny minority of objects are genuinely non-relocatable"
>
That tiny minority includes libstdc++ std::string, though. You might not
agree with internal pointer SSO, but branch-free reads have a considerable
performance benefit.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c33bb0a7372c051ca27a4b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Aug 6, 2015 at 11:43 AM, Ion Gazta=C3=B1aga <span dir=3D"ltr"><<a hr=
ef=3D"mailto:igaztanaga@gmail.com" target=3D"_blank">igaztanaga@gmail.com</=
a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=3D"">El =
06/08/2015 a las 10:35, David Rodr=C3=ADguez Ibeas escribi=C3=B3:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
I wasn't as much concerned with the destruction as the construction. Th=
e<br>
question comes back again as of whether a compiler could be smart enough<br=
>
to merge multiple 'memcpy', and while in the trivial case it would =
seem<br>
reasonable, I fear the are some cases that are not so trivial in the<br>
presence of padding, for example.<br>
</blockquote>
<br></span>
I don't think the compiler will merge it, at least many compilers don&#=
39;t optimize even simple loops into memcpy-s:<br>
<br>
<a href=3D"http://nadeausoftware.com/articles/2012/05/c_c_tip_how_copy_memo=
ry_quickly" rel=3D"noreferrer" target=3D"_blank">http://nadeausoftware.com/=
articles/2012/05/c_c_tip_how_copy_memory_quickly</a><br>
<br></blockquote><div><br></div>That's several years out of date; moder=
n compilers (gcc 5; clang 3.7; icc) have no problem ignoring padding and op=
timizing to memcpy. Example:=C2=A0<a href=3D"http://goo.gl/a0Xka7">http://g=
oo.gl/a0Xka7</a></div><div class=3D"gmail_quote"><br></div><div class=3D"gm=
ail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex">Of course in practice this kind o=
f destructive move semantics work, as used in BDE, Folly and other librarie=
s:<br>
<br>
<a href=3D"https://github.com/facebook/folly/blob/master/folly/docs/FBVecto=
r.md" rel=3D"noreferrer" target=3D"_blank">https://github.com/facebook/foll=
y/blob/master/folly/docs/FBVector.md</a><br>
<br>
"Only a tiny minority of objects are genuinely non-relocatable"<b=
r></blockquote><div><br></div><div>That tiny minority includes libstdc++ st=
d::string, though. You might not agree with internal pointer SSO, but branc=
h-free reads have a considerable performance benefit.</div><div>=C2=A0<br><=
/div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c33bb0a7372c051ca27a4b--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Thu, 6 Aug 2015 12:17:34 +0100
Raw View
--001a113492b87fcca2051ca2aa14
Content-Type: text/plain; charset=UTF-8
On Thu, Aug 6, 2015 at 12:04 PM, 'Edward Catmur' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> That's several years out of date; modern compilers (gcc 5; clang 3.7; icc)
> have no problem ignoring padding and optimizing to memcpy. Example:
> http://goo.gl/a0Xka7
>
> So that solves the padding issue, but we are left with merging multiple
memcpy into a single one, as in http://goo.gl/7SPzPl then again, if this
becomes common I'd assume compiler vendors would add that as an
optimization.
David
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113492b87fcca2051ca2aa14
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On Thu, Aug 6, 2015 at 12:04 PM, 'Edward Catmur' via ISO C++ Standa=
rd - Future Proposals <span dir=3D"ltr"><<a href=3D"mailto:std-proposals=
@isocpp.org" target=3D"_blank">std-proposals@isocpp.org</a>></span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_e=
xtra"><div class=3D"gmail_quote">That's several years out of date; mode=
rn compilers (gcc 5; clang 3.7; icc) have no problem ignoring padding and o=
ptimizing to memcpy. Example:=C2=A0<a href=3D"http://goo.gl/a0Xka7" target=
=3D"_blank">http://goo.gl/a0Xka7</a></div><div class=3D"gmail_quote"><br></=
div></div></div></blockquote><div>So that solves the padding issue, but we =
are left with merging multiple memcpy into a single one, as in <a href=3D"h=
ttp://goo.gl/7SPzPl">http://goo.gl/7SPzPl</a> then again, if this becomes c=
ommon I'd assume compiler vendors would add that as an optimization.<br=
><br>=C2=A0 =C2=A0David</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113492b87fcca2051ca2aa14--
.
Author: =?UTF-8?Q?Ion_Gazta=c3=b1aga?= <igaztanaga@gmail.com>
Date: Thu, 6 Aug 2015 13:33:09 +0200
Raw View
El 06/08/2015 a las 13:17, David Rodr=C3=ADguez Ibeas escribi=C3=B3:
>
> On Thu, Aug 6, 2015 at 12:04 PM, 'Edward Catmur' via ISO C++ Standard -
> Future Proposals <std-proposals@isocpp.org
> <mailto:std-proposals@isocpp.org>> wrote:
>
> That's several years out of date; modern compilers (gcc 5; clang
> 3.7; icc) have no problem ignoring padding and optimizing to memcpy.
> Example: http://goo.gl/a0Xka7
>
> So that solves the padding issue, but we are left with merging multiple
> memcpy into a single one, as in http://goo.gl/7SPzPl then again, if this
> becomes common I'd assume compiler vendors would add that as an
> optimization.
Right. Extremely simple destructive moves loop are not merged to a=20
memcpy. See:
http://goo.gl/7AN4wH
Best,
Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 6 Aug 2015 23:05:51 +0800
Raw View
--Apple-Mail=_208D2554-5CA2-4495-8DB4-AE37CDF06D54
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9308=E2=80=9306, at 7:18 AM, Ion Gazta=C3=B1aga <igaztanaga=
@gmail.com> wrote:
>=20
> Sorry for jumping in the middle of the discussion, I don't think the stan=
dard requires calling the destructor at all. The standard states that the l=
ifetime of an object ends when the storage is reused:
It=E2=80=99s fine to jump into the middle of the discussion, but please do =
consider the entire message to which you=E2=80=99re replying. You quoted on=
ly my first paragraph, your reply amounts to a recap of its last sentence, =
and the standard paragraph you quoted recaps the standard paragraph I cited=
there.
To summarize all three arguments in my last message:
1. The committee has expressed concern at unceremoniously ending object lif=
etimes. I don=E2=80=99t recall reviewing the rules there in the room, but t=
here was a sense of need for a core language unbless feature. Sanitizers pr=
ovide a practical motivation, and they might care to warn about things that=
are suspicious but not UB.
I wasn=E2=80=99t clear enough in saying =E2=80=9CAs I understand the origin=
al concern=E2=80=A6=E2=80=9D but I=E2=80=99m trying to reflect what I heard=
at the review of N4158. (The minutes record similar concerns in the review=
of N4393.) I did already note that the normative lifetime rules don=E2=80=
=99t seem to form a basis for this concern, but they don=E2=80=99t need to.
2. Nontrivial destructive move operations are important. It=E2=80=99s not s=
afe to assume that allocators and Allocator::pointer types are trivially de=
structible. I linked a practical example.
Another example was cited earlier (and again, since): std::string may use a=
self-reference to indicate SSO, in which case it isn=E2=80=99t trivially d=
estructive movable, but it could still provide a destructive move operation=
and avoid dirtying cache lines by nulling the source.
3. The standard library should have exemplary behavior. Absence of immediat=
e UB is only a weak argument in favor of an approach.
> On 2015=E2=80=9308=E2=80=9306, at 7:33 PM, Ion Gazta=C3=B1aga <igaztanaga=
@gmail.com> wrote:
>=20
> Right. Extremely simple destructive moves loop are not merged to a memcpy=
.. See:
>=20
> http://goo.gl/7AN4wH <http://goo.gl/7AN4wH>
Wrong. Alias analysis prevents using memcpy there. The compiler also prefer=
s to be working with POD types when generating memcpy, which is why the bas=
e slice technique works where yours doesn=E2=80=99t: http://goo.gl/ZL5yhW <=
http://goo.gl/ZL5yhW>
I had already provided a godbolt.org link in this thread. Please take the t=
ime to review earlier posts.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_208D2554-5CA2-4495-8DB4-AE37CDF06D54
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D""><b=
r class=3D""></div><div><blockquote type=3D"cite" class=3D""><div class=3D"=
">On 2015=E2=80=9308=E2=80=9306, at 7:18 AM, Ion Gazta=C3=B1aga <<a href=
=3D"mailto:igaztanaga@gmail.com" class=3D"">igaztanaga@gmail.com</a>> wr=
ote:</div><br class=3D"Apple-interchange-newline"><div class=3D""><span cla=
ss=3D"" style=3D"float: none; display: inline !important;">Sorry for jumpin=
g in the middle of the discussion, I don't think the standard requires call=
ing the destructor at all. The standard states that the lifetime of an obje=
ct ends when the storage is reused:</span><br class=3D""></div></blockquote=
></div><br class=3D""><div class=3D"">It=E2=80=99s fine to jump into the mi=
ddle of the discussion, but please do consider the entire message to which =
you=E2=80=99re replying. You quoted only my first paragraph, your reply amo=
unts to a recap of its last sentence, and the standard paragraph you quoted=
recaps the standard paragraph I cited there.</div><div class=3D""><br clas=
s=3D""></div><div class=3D"">To summarize all three arguments in my last me=
ssage:</div><div class=3D""><br class=3D""></div><div class=3D"">1. The com=
mittee has expressed concern at unceremoniously ending object lifetimes. I =
don=E2=80=99t recall reviewing the rules there in the room, but there was a=
sense of need for a core language unbless feature. Sanitizers provide a pr=
actical motivation, and they might care to warn about things that are suspi=
cious but not UB.</div><div class=3D""><br class=3D""></div><div class=3D""=
>I wasn=E2=80=99t clear enough in saying =E2=80=9CAs I understand the origi=
nal concern=E2=80=A6=E2=80=9D but I=E2=80=99m trying to reflect what I hear=
d at the review of N4158. (The minutes record similar concerns in the revie=
w of N4393.) I did already note that the normative lifetime rules don=E2=80=
=99t seem to form a basis for this concern, but they don=E2=80=99t need to.=
</div><div class=3D""><br class=3D""></div><div class=3D"">2. Nontrivial de=
structive move operations are important. It=E2=80=99s not safe to assume th=
at allocators and <font face=3D"Courier" class=3D"">Allocator::pointer=
</font> types are trivially destructible. I linked a practical example=
..</div><div class=3D""><br class=3D""></div><div class=3D"">Another example=
was cited earlier (and again, since): <font face=3D"Courier" class=3D=
"">std::string</font> may use a self-reference to indicate SSO, in whi=
ch case it isn=E2=80=99t trivially destructive movable, but it could still =
provide a destructive move operation and avoid dirtying cache lines by null=
ing the source.</div><div class=3D""><br class=3D""></div><div class=3D"">3=
.. The standard library should have exemplary behavior. Absence of immediate=
UB is only a weak argument in favor of an approach.</div><div class=3D""><=
br class=3D""></div><div class=3D""><br class=3D""></div><div><blockquote t=
ype=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9308=E2=80=9306, at 7=
:33 PM, Ion Gazta=C3=B1aga <<a href=3D"mailto:igaztanaga@gmail.com" clas=
s=3D"">igaztanaga@gmail.com</a>> wrote:</div><br class=3D"Apple-intercha=
nge-newline"><div class=3D""><span style=3D"font-family: Helvetica; font-si=
ze: 12px; font-style: normal; font-variant: normal; font-weight: normal; le=
tter-spacing: normal; line-height: normal; orphans: auto; text-align: start=
; text-indent: 0px; text-transform: none; white-space: normal; widows: auto=
; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: =
inline !important;" class=3D"">Right. Extremely simple destructive moves lo=
op are not merged to a memcpy. See:</span><br style=3D"font-family: Helveti=
ca; font-size: 12px; font-style: normal; font-variant: normal; font-weight:=
normal; letter-spacing: normal; line-height: normal; orphans: auto; text-a=
lign: start; text-indent: 0px; text-transform: none; white-space: normal; w=
idows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""=
><br style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant: normal; font-weight: normal; letter-spacing: normal; line-hei=
ght: normal; orphans: auto; text-align: start; text-indent: 0px; text-trans=
form: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-t=
ext-stroke-width: 0px;" class=3D""><a href=3D"http://goo.gl/7AN4wH" style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D"">http://goo.gl/7AN4wH</a><br style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-=
weight: normal; letter-spacing: normal; line-height: normal; orphans: auto;=
text-align: start; text-indent: 0px; text-transform: none; white-space: no=
rmal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" cla=
ss=3D""></div></blockquote><br class=3D""></div><div>Wrong. Alias analysis =
prevents using <font face=3D"Courier" class=3D"">memcpy</font> there. The c=
ompiler also prefers to be working with POD types when generating <font fac=
e=3D"Courier" class=3D"">memcpy</font>, which is why the base slice techniq=
ue works where yours doesn=E2=80=99t: <a href=3D"http://goo.gl/ZL5yhW"=
class=3D"">http://goo.gl/ZL5yhW</a></div><div><br class=3D""></div><div>I =
had already provided a <a href=3D"http://godbolt.org" class=3D"">godbolt.or=
g</a> link in this thread. Please take the time to review earlier posts.</d=
iv><div><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_208D2554-5CA2-4495-8DB4-AE37CDF06D54--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Thu, 06 Aug 2015 11:36:42 -0400
Raw View
On 2015-08-06 04:35, David Rodr=C3=ADguez Ibeas wrote:
> I wasn't as much concerned with the destruction as the construction. The
> question comes back again as of whether a compiler could be smart enough =
to
> merge multiple 'memcpy', and while in the trivial case it would seem
> reasonable, I fear the are some cases that are not so trivial in the
> presence of padding, for example.
I think the 'constructing destructor' pattern, with ability to check for
those being trivial, would solve this problem (as well as allowing
cheaper relocations even for classes that are self-referencing). Users
that care (e.g. containers) can check for defaulted 'constructing
destructors' and explicitly do a memmove instead; no compiler cleverness
needed.
It occurs to me that *ALL* classes should *have* a cting-dtor, but that
the same is not necessarily trivial.
The implicit behavior should be to move-construct the target and then
destruct the object. The explicitly defaulted behavior should be a
memberwise call to the cting-dtors of each member. A trivial cting-dtor
(e.g. implicit for POD types) is a memcpy. The compiler should be able
to combine multiple trivial cting-dtors in a compound object into one or
more memcpy's (e.g. could be more than one in case of a member with
non-trivial cting-dtor in the middle of the compound type).
This allows us to easily optimize the relocation operation for types
that consist /mainly, but not entirely/ of trivially relocatable
members. It also allows us to potentially relax the rules (either now,
or at some future date) for when the implicit cting-dtor can be made
trivial. This would allow for example 'struct Point { double x, y; };'
to be given a trivial cting-dtor without having to explicitly declare a
defaulted cting-dtor, which is an obvious win.
IOW:
// implicit cting-dtor
foo::~foo(foo* new_foo) // or char* / void*
{
new (new_foo)(std::move(this));
this->~foo();
}
// trivial cting-dtor
foo::~foo(foo* new_foo) // or char* / void*
{
memcpy(new_foo, this, sizeof(foo));
__builtin_create<foo>(new_foo); // bless new object as created
__builtin_release(this); // pedantic, probably no-op
}
(I think having a concept of triviality of the cting-dtor might help
with some of the other examples you gave...)
> To some extents these are concerns more on the feasibility of the
> implementation (optimizer) than the language itself, and it can be argued
> that if a tag for the constructor, a wrapper ('destructive_move_ref<T>()'=
)
> or any other mechanism is standardized, compiler writers would have an
> incentive to work towards providing these optimizations.
Yes. (And again, having triviality would enable the library to tackle
probably many of the most critical cases if the optimizer can't.)
> Yet another concern is that the source object is left in an invalid state=
,
> which opens the path for misuse
If you implement this by cting-dtor, the source *has been destroyed*. So
while the above is true, it's no worse than:
pfoo->~foo();
// referring again to pfoo at this point would be bad...
The invocation would need to be something like:
// allocate non-typed buffer e.g. using malloc
old_ptr->~T(new_ptr);
// *old_ptr is now destroyed, new_ptr is now a constructed T
(And I believe the onus is already on the compiler to know that the
object is already destroyed if a dtor is explicitly called?)
> for example the implementation of
> 'insert_impl' above could be attempted by a non-expert user as:
>=20
> vector<T>::insert_impl(iterator pos, T&& value, destructive_move_tag)
> T tmp(move(value));
This can't work (i.e. can't use a cting-dtor); rvalue reference
semantics require that 'value' is left in a constructed (if unspecified)
state. Use emplace if you want to avoid the additional allocation.
The only other way this could be solved is to invent a new indirection
type, probably '~', that says that the callee will destroy the object.
Anyway, this isn't the major bottleneck, which is relocating a large
number of contiguous values e.g. when resizing an array.
--=20
Matthew
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Ion_Gazta=c3=b1aga?= <igaztanaga@gmail.com>
Date: Thu, 6 Aug 2015 22:08:19 +0200
Raw View
David Krauss wrote:
> It=E2=80=99s fine to jump into the middle of the discussion, but please d=
o
> consider the entire message to which you=E2=80=99re replying. You quoted =
only my
> first paragraph, your reply amounts to a recap of its last sentence, and
> the standard paragraph you quoted recaps the standard paragraph I cited
> there.
Sorry for any noise, it was not my intention.
> To summarize all three arguments in my last message:
Thanks, that will help me summarize also my points.
> 1. The committee has expressed concern at unceremoniously ending object
> lifetimes. I don=E2=80=99t recall reviewing the rules there in the room, =
but
> there was a sense of need for a core language unbless feature.
> Sanitizers provide a practical motivation, and they might care to warn
> about things that are suspicious but not UB.
That's a logical concern, my only comment was that current core language=20
is quite clear IMHO. In theory, library-only destructive move semantics=20
are possible, this is a good thing since we could just implement a=20
library to explore the field and catch potential problems. Current rules=20
might not be sanitizer-friendly, though. There is room from improvement,=20
no doubt.
> 2. Nontrivial destructive move operations are important. It=E2=80=99s not=
safe
> to assume that allocators and Allocator::pointer types are trivially
> destructible. I linked a practical example.
>
> Another example was cited earlier (and again, since): std::string may
> use a self-reference to indicate SSO, in which case it isn=E2=80=99t triv=
ially
> destructive movable, but it could still provide a destructive move
> operation and avoid dirtying cache lines by nulling the source.
We agree that they are important. There are quite a few self-referencing=20
types in the library, like std::slist/std::list/std::map/set=20
implementations.
> 3. The standard library should have exemplary behavior. Absence of
> immediate UB is only a weak argument in favor of an approach.
Agreed.
Best,
Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?Ion_Gazta=c3=b1aga?= <igaztanaga@gmail.com>
Date: Thu, 6 Aug 2015 22:55:03 +0200
Raw View
David Krauss wrote:
> Wrong. Alias analysis prevents using memcpy there. The compiler also
> prefers to be working with POD types when generating memcpy, which is
> why the base slice technique works where yours doesn=E2=80=99t: http://go=
o.gl/ZL5yhW
Thanks for the aliasing point. It's strange that POD-ness restricts the=20
memcpy-ability. Is also interesting to see that GCC (5.2) skips memcpy=20
on both cases.
Best,
Ion
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: isocppgroup@denisbider.com
Date: Fri, 7 Aug 2015 00:50:22 -0700 (PDT)
Raw View
------=_Part_1815_2139936778.1438933822949
Content-Type: multipart/alternative;
boundary="----=_Part_1816_1076375336.1438933822950"
------=_Part_1816_1076375336.1438933822950
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I agree with this suggestion. I think the move destructor idea is ingenious=
..
A move destructor:
- Solves the problem of figuring out syntax for a destructive move=20
constructor. Destructors can't have overloads, so this works great. (The=20
parameter to the move destructor should probably a reference, though, not a=
=20
pointer.)
- Provides for an easy way to declare a type relocatable AND provide=20
compiler inference:
struct A : B {
~A(A& x) =3D default;
C x;
};
The defaulted move destructor can do whatever is appropriate depending on=
=20
the definitions of B and C types.
A move destructor can even be generated implicitly in certain cases.
Genius idea. Elegant syntax. Covers all use cases. Supports types that=20
require patch-ups for relocation. Completely general.
Thumbs up!
On Wednesday, August 5, 2015 at 3:41:02 AM UTC-6, David Rodr=C3=ADguez Ibea=
s=20
wrote:
>
>
> On Wed, Aug 5, 2015 at 6:03 AM, David Krauss <pot...@gmail.com=20
> <javascript:>> wrote:
>
>>
>> The normative permission to end an object=E2=80=99s lifetime without cal=
ling its=20
>> nontrivial destructor =C2=A73.8/4 has a stern warning about undefined be=
havior.=20
>> The standard library should avoid skipping nontrivial destructors.
>>
>
> The warning in 3.8/4 would not apply to a type that has been marked as=20
> destructive-movable as marking it as such would be the programmer's=20
> blessing that it is fine (and even desirable) to skip the destructor, tha=
t=20
> it is fine and desirable for the program not to have the side effects of=
=20
> the destructor when used in a destructive move operation.
> =20
>
>> Even more convenient would be getting an an implicit definition to do it=
=20
>> for you, regardless of triviality. But, that sticks something like=20
>> destructive_move_ref into the core language.
>>
>
> Having a 'destructive_move_ref' in the core language could also allow fo=
r=20
> alternative implementations of destructive-move-constructor where a self=
=20
> referencing type could overload an specific constructor/destructor to do=
=20
> something like memcpy + patching of references. For example, in the case =
of=20
> a string doing RVO and holding a possibly self-referencing pointer it cou=
ld=20
> do a memcpy of the string object and conditionally adjust the pointer to=
=20
> the internal buffer if it is using the small buffer. Then again, at this=
=20
> time it would (guessing) not be more efficient than the equivalent=20
> move-constructor.
>
> On a wicked attempt at bike-shedding the operation, we could add a=20
> move-destructor:
>
> template <typename T, typename A =3D std::allocator<T> >
> class list {
> // Imagine this as Dinkumware's implementation of 'std::list', assume=
=20
> SFINAE for a destructive-movable allocator
> Node *sentry; // for exposition
>
> list(list&& src) noexcept(false);
> ~list(void *dst) noexcept(true) { // ~list([[uninitialized]] list *dst=
)
> memcpy(dst, this, sizeof *this);
> }
>
> With that move-destructor being blessed by the standard as both=20
> terminating the lifetime of 'this' and creating a new object over 'dst',=
=20
> behaviorally equivalent, with respect to lifetimes, to:
>
> new (dst) list(std::move(*this));
> this->~list();
>
> The optimizer would have to figure out, does not seem too complicated,=20
> that multiple memcpy's for contiguous memory can be coalesced into a sing=
le=20
> memcpy/memmove. The 'memmove' is because while the move-destructor canno=
t=20
> be called (documented as undefined behavior) with 'dst =3D=3D this', a lo=
op of=20
> move-destructor's may be shifting elements in overlapping regions in a=20
> vector.
>
> The move-destructor would not be implicitly declared, but could be=20
> defaulted to just do the memcpy, so implementors can just do:
>
> ~list(void *dst) =3D default;
>
> which would at the same time be detectable by a 'is_move_destructible<T>'=
,=20
> the real change to 'std::list' in such implementations would be:
>
> template <typename T, typename A =3D allocator<T>>
> class list {
> // ...
> template <typename U =3D A, typename _ =3D typename=20
> enable_if<is_move_destructible<A<T>>::type>
> ~list(void *dst) =3D default
>
> Which is a bit obscure, but not too horrible for a library implementation=
..=20
> (I feel that the argument being 'list *dst' would be nicer for the=20
> developer, but I am not sure about passing a pointer to a memory location=
=20
> that is not a 'T' as a 'T*', if that is fine I'd prefer to have the=20
> argument typed).
>
> David
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1816_1076375336.1438933822950
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I agree with this suggestion.=C2=A0I think=C2=A0the m=
ove destructor idea is ingenious.</div><div><br></div><div>A move destructo=
r:</div><div><br></div><div>- Solves the problem of figuring out syntax for=
a destructive move constructor. Destructors can't have overloads, so t=
his works great. (The parameter to the move destructor should probably a re=
ference, though, not a pointer.)</div><div><br></div><div>- Provides for an=
easy way to declare a type relocatable AND provide compiler inference:</di=
v><div><br></div><div><font face=3D"courier new,monospace">struct A : B=C2=
=A0{</font></div><div><font face=3D"Courier New"><div><font face=3D"courier=
new,monospace">=C2=A0 ~A(A& x) =3D default;</font></div>=C2=A0 C x;</f=
ont></div><div><font face=3D"courier new,monospace">};</font></div><div><br=
></div><div>The defaulted move destructor can do whatever is appropriate de=
pending on the definitions of B and C types.</div><div><br></div><div>A mov=
e destructor can even be generated implicitly in certain cases.</div><div><=
br></div><div>Genius idea.=C2=A0Elegant syntax. Covers all use cases.=C2=A0=
Supports=C2=A0types that require patch-ups for relocation. Completely gener=
al.</div><div><br></div><div>Thumbs up!</div><div><br><br>On Wednesday, Aug=
ust 5, 2015 at 3:41:02 AM UTC-6, David Rodr=C3=ADguez Ibeas wrote:</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-=
left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; b=
order-left-style: solid;"><div dir=3D"ltr"><br><div><br><div class=3D"gmail=
_quote">On Wed, Aug 5, 2015 at 6:03 AM, David Krauss <span dir=3D"ltr"><=
<a onmousedown=3D"this.href=3D'javascript:';return true;" onclick=
=3D"this.href=3D'javascript:';return true;" href=3D"javascript:" ta=
rget=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"fPCOnBMlEAAJ">pot=
....@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb=
(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div st=
yle=3D"-ms-word-wrap: break-word;"><div><div><br></div><div>The normative p=
ermission to end an object=E2=80=99s lifetime without calling its nontrivia=
l destructor =C2=A73.8/4 has a stern warning about undefined behavior. The =
standard library should avoid skipping nontrivial destructors.</div></div><=
/div></blockquote><div><br>The warning in 3.8/4 would not apply to a type t=
hat has been marked as destructive-movable as marking it as such would be t=
he programmer's blessing that it is fine (and even desirable) to skip t=
he destructor, that it is fine and desirable for the program not to have th=
e side effects of the destructor when used in a destructive move operation.=
<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border=
-left-width: 1px; border-left-style: solid;"><div style=3D"-ms-word-wrap: b=
reak-word;"><div><span><div>Even more convenient would be getting an an imp=
licit definition to do it for you, regardless of triviality. But, that stic=
ks something like <font face=3D"Courier">destructive_move_ref</font> into t=
he core language.</div></span></div></div></blockquote><div><br></div><div>=
=C2=A0Having a 'destructive_move_ref' in the core language could al=
so allow for alternative implementations of destructive-move-constructor wh=
ere a self referencing type could overload an specific constructor/destruct=
or to do something like memcpy + patching of references. For example, in th=
e case of a string doing RVO and holding a possibly self-referencing pointe=
r it could do a memcpy of the string object and conditionally adjust the po=
inter to the internal buffer if it is using the small buffer.=C2=A0 Then ag=
ain, at this time it would (guessing) not be more efficient than the equiva=
lent move-constructor.<br><br>On a wicked attempt at bike-shedding the oper=
ation, we could add a move-destructor:<br><br>template <typename T, type=
name A =3D std::allocator<T> ><br>class list {<br>=C2=A0 =C2=A0// =
Imagine this as Dinkumware's implementation of 'std::list', ass=
ume SFINAE for a destructive-movable allocator<br>=C2=A0 =C2=A0Node *sentry=
; =C2=A0// for exposition<br><br>=C2=A0 =C2=A0list(list&& src) noex=
cept(false);<br>=C2=A0 =C2=A0~list(void *dst) noexcept(true) { // ~list([[u=
ninitialized]] list *dst)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0memcpy(dst, this, s=
izeof *this);</div><div>=C2=A0 =C2=A0}<br><br>With that move-destructor bei=
ng blessed by the standard as both terminating the lifetime of 'this=
9; and creating a new object over 'dst', behaviorally equivalent, w=
ith respect to lifetimes, to:<br><br>new (dst) list(std::move(*this));<br>t=
his->~list();<br><br>The optimizer would have to figure out, does not se=
em too complicated, that multiple memcpy's for contiguous memory can be=
coalesced into a single memcpy/memmove.=C2=A0 The 'memmove' is bec=
ause while the move-destructor cannot be called (documented as undefined be=
havior) with 'dst =3D=3D this', a loop of move-destructor's may=
be shifting elements in overlapping regions in a vector.<br><br>The move-d=
estructor would not be implicitly declared, but could be defaulted to just =
do the memcpy, so implementors can just do:<br><br>~list(void *dst) =3D def=
ault;<br><br>which would at the same time be detectable by a 'is_move_d=
estructible<T>', the real change to 'std::list' in such i=
mplementations would be:<br><br>template <typename T, typename A =3D all=
ocator<T>><br>class list {<br>// ...<br>=C2=A0 =C2=A0 template <=
;typename U =3D A, typename _ =3D typename enable_if<is_move_<wbr>destru=
ctible<A<T>>::type><br>=C2=A0 =C2=A0 ~list(void *dst) =3D de=
fault<br><br>Which is a bit obscure, but not too horrible for a library imp=
lementation. (I feel that the argument being 'list *dst' would be n=
icer for the developer, but I am not sure about passing a pointer to a memo=
ry location that is not a 'T' as a 'T*', if that is fine I&=
#39;d prefer to have the argument typed).<br><br>=C2=A0 =C2=A0 David</div><=
/div></div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1816_1076375336.1438933822950--
------=_Part_1815_2139936778.1438933822949--
.
Author: isocppgroup@denisbider.com
Date: Fri, 7 Aug 2015 01:00:59 -0700 (PDT)
Raw View
------=_Part_1885_538521691.1438934459313
Content-Type: multipart/alternative;
boundary="----=_Part_1886_1219900252.1438934459313"
------=_Part_1886_1219900252.1438934459313
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
It would be nice if the move destructor does not expose too much of a "nuts=
=20
and bolts" interface - such as requiring the developer to call placement=20
new, explicitly call a destructor, and so forth.
What if the move destructor is called with an object reference that has=20
ALREADY had memcpy performed, and is expected to simply perform a patch-up?
This way, if the move destructor does nothing, the object has been=20
trivially moved. No additional code required.
If the move destructor is declared deleted, the object cannot be=20
destructively moved.
The way an array of objects is moved could then consist of:
1. memcpy whole array of objects
2. call move destructors to perform any patch-ups
Static analysis tools would detect step (2) as transition of objects to new=
=20
location.
No need to perform magic to consolidate the memory copies, and static=20
analysis works.
On Thursday, August 6, 2015 at 9:36:58 AM UTC-6, Matthew Woehlke wrote:
> On 2015-08-06 04:35, David Rodr=C3=ADguez Ibeas wrote:=20
> > I wasn't as much concerned with the destruction as the construction. Th=
e=20
> > question comes back again as of whether a compiler could be smart enoug=
h=20
> to=20
> > merge multiple 'memcpy', and while in the trivial case it would seem=20
> > reasonable, I fear the are some cases that are not so trivial in the=20
> > presence of padding, for example.=20
>
> I think the 'constructing destructor' pattern, with ability to check for=
=20
> those being trivial, would solve this problem (as well as allowing=20
> cheaper relocations even for classes that are self-referencing). Users=20
> that care (e.g. containers) can check for defaulted 'constructing=20
> destructors' and explicitly do a memmove instead; no compiler cleverness=
=20
> needed.=20
>
> It occurs to me that *ALL* classes should *have* a cting-dtor, but that=
=20
> the same is not necessarily trivial.=20
>
> The implicit behavior should be to move-construct the target and then=20
> destruct the object. The explicitly defaulted behavior should be a=20
> memberwise call to the cting-dtors of each member. A trivial cting-dtor=
=20
> (e.g. implicit for POD types) is a memcpy. The compiler should be able=20
> to combine multiple trivial cting-dtors in a compound object into one or=
=20
> more memcpy's (e.g. could be more than one in case of a member with=20
> non-trivial cting-dtor in the middle of the compound type).=20
>
> This allows us to easily optimize the relocation operation for types=20
> that consist /mainly, but not entirely/ of trivially relocatable=20
> members. It also allows us to potentially relax the rules (either now,=20
> or at some future date) for when the implicit cting-dtor can be made=20
> trivial. This would allow for example 'struct Point { double x, y; };'=20
> to be given a trivial cting-dtor without having to explicitly declare a=
=20
> defaulted cting-dtor, which is an obvious win.=20
>
>
> IOW:=20
>
> // implicit cting-dtor=20
> foo::~foo(foo* new_foo) // or char* / void*=20
> {=20
> new (new_foo)(std::move(this));=20
> this->~foo();=20
> }=20
>
> // trivial cting-dtor=20
> foo::~foo(foo* new_foo) // or char* / void*=20
> {=20
> memcpy(new_foo, this, sizeof(foo));=20
> __builtin_create<foo>(new_foo); // bless new object as created=20
> __builtin_release(this); // pedantic, probably no-op=20
> }=20
>
> (I think having a concept of triviality of the cting-dtor might help=20
> with some of the other examples you gave...)=20
>
> > To some extents these are concerns more on the feasibility of the=20
> > implementation (optimizer) than the language itself, and it can be=20
> argued=20
> > that if a tag for the constructor, a wrapper=20
> ('destructive_move_ref<T>()')=20
> > or any other mechanism is standardized, compiler writers would have an=
=20
> > incentive to work towards providing these optimizations.=20
>
> Yes. (And again, having triviality would enable the library to tackle=20
> probably many of the most critical cases if the optimizer can't.)=20
>
> > Yet another concern is that the source object is left in an invalid=20
> state,=20
> > which opens the path for misuse=20
>
> If you implement this by cting-dtor, the source *has been destroyed*. So=
=20
> while the above is true, it's no worse than:=20
>
> pfoo->~foo();=20
> // referring again to pfoo at this point would be bad...=20
>
> The invocation would need to be something like:=20
>
> // allocate non-typed buffer e.g. using malloc=20
> old_ptr->~T(new_ptr);=20
> // *old_ptr is now destroyed, new_ptr is now a constructed T=20
>
> (And I believe the onus is already on the compiler to know that the=20
> object is already destroyed if a dtor is explicitly called?)=20
>
> > for example the implementation of=20
> > 'insert_impl' above could be attempted by a non-expert user as:=20
> >=20
> > vector<T>::insert_impl(iterator pos, T&& value, destructive_move_tag)=
=20
> > T tmp(move(value));=20
>
> This can't work (i.e. can't use a cting-dtor); rvalue reference=20
> semantics require that 'value' is left in a constructed (if unspecified)=
=20
> state. Use emplace if you want to avoid the additional allocation.=20
>
> The only other way this could be solved is to invent a new indirection=20
> type, probably '~', that says that the callee will destroy the object.=20
>
> Anyway, this isn't the major bottleneck, which is relocating a large=20
> number of contiguous values e.g. when resizing an array.=20
>
> --=20
> Matthew=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1886_1219900252.1438934459313
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>It would be nice if the move destructor does not expo=
se too much of a "nuts and bolts" interface -=C2=A0such as requir=
ing the developer to call placement new, explicitly call a destructor, and =
so forth.</div><div><br></div><div>What if the move destructor is called wi=
th an object reference that has ALREADY had memcpy performed, and is expect=
ed to simply perform a patch-up?</div><div><br></div><div>This way, if the =
move destructor does nothing, the object has been trivially moved. No addit=
ional code required.</div><div><br></div><div>If the move destructor is dec=
lared deleted, the object cannot be destructively moved.</div><div><br></di=
v><div>The way an array of objects is moved could then consist of:</div><di=
v><br></div><div>1. memcpy whole array of objects</div><div>2. call move de=
structors to perform any patch-ups</div><p><br></p><div>Static analysis too=
ls would detect step (2) as transition of objects to new location.</div><di=
v><br></div><div>No need to perform magic to consolidate the memory copies,=
and=C2=A0static analysis works.</div><div><br><br>On Thursday, August 6, 2=
015 at 9:36:58 AM UTC-6, Matthew Woehlke wrote:</div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-l=
eft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: s=
olid;">On 2015-08-06 04:35, David Rodr=C3=ADguez Ibeas wrote:
<br>> I wasn't as much concerned with the destruction as the constru=
ction. The
<br>> question comes back again as of whether a compiler could be smart =
enough to
<br>> merge multiple 'memcpy', and while in the trivial case it =
would seem
<br>> reasonable, I fear the are some cases that are not so trivial in t=
he
<br>> presence of padding, for example.
<br>
<br>I think the 'constructing destructor' pattern, with ability to =
check for
<br>those being trivial, would solve this problem (as well as allowing
<br>cheaper relocations even for classes that are self-referencing). Users
<br>that care (e.g. containers) can check for defaulted 'constructing
<br>destructors' and explicitly do a memmove instead; no compiler cleve=
rness
<br>needed.
<br>
<br>It occurs to me that *ALL* classes should *have* a cting-dtor, but that
<br>the same is not necessarily trivial.
<br>
<br>The implicit behavior should be to move-construct the target and then
<br>destruct the object. The explicitly defaulted behavior should be a
<br>memberwise call to the cting-dtors of each member. A trivial cting-dtor
<br>(e.g. implicit for POD types) is a memcpy. The compiler should be able
<br>to combine multiple trivial cting-dtors in a compound object into one o=
r
<br>more memcpy's (e.g. could be more than one in case of a member with
<br>non-trivial cting-dtor in the middle of the compound type).
<br>
<br>This allows us to easily optimize the relocation operation for types
<br>that consist /mainly, but not entirely/ of trivially relocatable
<br>members. It also allows us to potentially relax the rules (either now,
<br>or at some future date) for when the implicit cting-dtor can be made
<br>trivial. This would allow for example 'struct Point { double x, y; =
};'
<br>to be given a trivial cting-dtor without having to explicitly declare a
<br>defaulted cting-dtor, which is an obvious win.
<br>
<br>
<br>IOW:
<br>
<br>=C2=A0 // implicit cting-dtor
<br>=C2=A0 foo::~foo(foo* new_foo) // or char* / void*
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 new (new_foo)(std::move(this));
<br>=C2=A0 =C2=A0 this->~foo();
<br>=C2=A0 }
<br>
<br>=C2=A0 // trivial cting-dtor
<br>=C2=A0 foo::~foo(foo* new_foo) // or char* / void*
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 memcpy(new_foo, this, sizeof(foo));
<br>=C2=A0 =C2=A0 __builtin_create<foo>(new_foo)<wbr>; // bless new o=
bject as created
<br>=C2=A0 =C2=A0 __builtin_release(this); // pedantic, probably no-op
<br>=C2=A0 }
<br>
<br>(I think having a concept of triviality of the cting-dtor might help
<br>with some of the other examples you gave...)
<br>
<br>> To some extents these are concerns more on the feasibility of the
<br>> implementation (optimizer) than the language itself, and it can be=
argued
<br>> that if a tag for the constructor, a wrapper ('destructive_mov=
e_ref<T>()')
<br>> or any other mechanism is standardized, compiler writers would hav=
e an
<br>> incentive to work towards providing these optimizations.
<br>
<br>Yes. (And again, having triviality would enable the library to tackle
<br>probably many of the most critical cases if the optimizer can't.)
<br>
<br>> Yet another concern is that the source object is left in an invali=
d state,
<br>> which opens the path for misuse
<br>
<br>If you implement this by cting-dtor, the source *has been destroyed*. S=
o
<br>while the above is true, it's no worse than:
<br>
<br>=C2=A0 pfoo->~foo();
<br>=C2=A0 // referring again to pfoo at this point would be bad...
<br>
<br>The invocation would need to be something like:
<br>
<br>=C2=A0 // allocate non-typed buffer e.g. using malloc
<br>=C2=A0 old_ptr->~T(new_ptr);
<br>=C2=A0 // *old_ptr is now destroyed, new_ptr is now a constructed T
<br>
<br>(And I believe the onus is already on the compiler to know that the
<br>object is already destroyed if a dtor is explicitly called?)
<br>
<br>> for example the implementation of
<br>> 'insert_impl' above could be attempted by a non-expert use=
r as:
<br>>=20
<br>> vector<T>::insert_impl(<wbr>iterator pos, T&& value,=
destructive_move_tag)
<br>> =C2=A0 =C2=A0T tmp(move(value));
<br>
<br>This can't work (i.e. can't use a cting-dtor); rvalue reference
<br>semantics require that 'value' is left in a constructed (if uns=
pecified)
<br>state. Use emplace if you want to avoid the additional allocation.
<br>
<br>The only other way this could be solved is to invent a new indirection
<br>type, probably '~', that says that the callee will destroy the =
object.
<br>
<br>Anyway, this isn't the major bottleneck, which is relocating a larg=
e
<br>number of contiguous values e.g. when resizing an array.
<br>
<br>--=20
<br>Matthew
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1886_1219900252.1438934459313--
------=_Part_1885_538521691.1438934459313--
.
Author: isocppgroup@denisbider.com
Date: Fri, 7 Aug 2015 02:03:59 -0700 (PDT)
Raw View
------=_Part_85_488097591.1438938239854
Content-Type: multipart/alternative;
boundary="----=_Part_86_2091785587.1438938239855"
------=_Part_86_2091785587.1438938239855
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
To avoid any issues with the memcpy/memmove step (1) being separate from=20
the call-move-destructor step (2), we can make the compiler generate code=
=20
that encapsulates this; similar in nature to how the keywords new and delet=
e=20
work.
So, if we have an object with a move destructor:
class StringType {
~StringType(StringType& x) {
// x is already a bitwise copy of *this
// perform patch-up of self-references
}};
The developer does not invoke this directly, but via a compiler-generated=
=20
static destructor, declared like this:
StringType* StringType::~StringType(void* d, StringType* s, std::size_t n=
=3D1);
When this is invoked, the *compiler* then generates the equivalent of this:
memmove(d, s, n * sizeof(StringType));
StringType* dt =3D (StringType*) d;for (std::size_t i=3D0; i!=3Dn; ++i)
s[i].~StringType(dt[i]);return dt;
For trivial types, and for types that are trivially relocatable (empty move=
=20
destructors) - the for loop is simply optimized away.
For types that require patching-up during relocation, the for loop calls=20
the move destructors that take care of it.
But crucially - the developer does not perform these individual steps. The=
=20
developer just calls:
StringType* dest =3D StringType::~StringType(destptr, src, n);
This construction doesn't work with realloc - it requires simultaneous=20
access to both old memory and new, which realloc does not provide - but=20
some type of realloc_in_place_only could be provided for this purpose.
On Friday, August 7, 2015 at 2:00:59 AM UTC-6, isocp...@denisbider.com=20
wrote:
> It would be nice if the move destructor does not expose too much of a=20
> "nuts and bolts" interface - such as requiring the developer to call=20
> placement new, explicitly call a destructor, and so forth.
>
> What if the move destructor is called with an object reference that has=
=20
> ALREADY had memcpy performed, and is expected to simply perform a patch-u=
p?
>
> This way, if the move destructor does nothing, the object has been=20
> trivially moved. No additional code required.
>
> If the move destructor is declared deleted, the object cannot be=20
> destructively moved.
>
> The way an array of objects is moved could then consist of:
>
> 1. memcpy whole array of objects
> 2. call move destructors to perform any patch-ups
>
>
> Static analysis tools would detect step (2) as transition of objects to=
=20
> new location.
>
> No need to perform magic to consolidate the memory copies, and static=20
> analysis works.
>
>
> On Thursday, August 6, 2015 at 9:36:58 AM UTC-6, Matthew Woehlke wrote:
>
>> On 2015-08-06 04:35, David Rodr=C3=ADguez Ibeas wrote:=20
>> > I wasn't as much concerned with the destruction as the construction.=
=20
>> The=20
>> > question comes back again as of whether a compiler could be smart=20
>> enough to=20
>> > merge multiple 'memcpy', and while in the trivial case it would seem=
=20
>> > reasonable, I fear the are some cases that are not so trivial in the=
=20
>> > presence of padding, for example.=20
>>
>> I think the 'constructing destructor' pattern, with ability to check for=
=20
>> those being trivial, would solve this problem (as well as allowing=20
>> cheaper relocations even for classes that are self-referencing). Users=
=20
>> that care (e.g. containers) can check for defaulted 'constructing=20
>> destructors' and explicitly do a memmove instead; no compiler cleverness=
=20
>> needed.=20
>>
>> It occurs to me that *ALL* classes should *have* a cting-dtor, but that=
=20
>> the same is not necessarily trivial.=20
>>
>> The implicit behavior should be to move-construct the target and then=20
>> destruct the object. The explicitly defaulted behavior should be a=20
>> memberwise call to the cting-dtors of each member. A trivial cting-dtor=
=20
>> (e.g. implicit for POD types) is a memcpy. The compiler should be able=
=20
>> to combine multiple trivial cting-dtors in a compound object into one or=
=20
>> more memcpy's (e.g. could be more than one in case of a member with=20
>> non-trivial cting-dtor in the middle of the compound type).=20
>>
>> This allows us to easily optimize the relocation operation for types=20
>> that consist /mainly, but not entirely/ of trivially relocatable=20
>> members. It also allows us to potentially relax the rules (either now,=
=20
>> or at some future date) for when the implicit cting-dtor can be made=20
>> trivial. This would allow for example 'struct Point { double x, y; };'=
=20
>> to be given a trivial cting-dtor without having to explicitly declare a=
=20
>> defaulted cting-dtor, which is an obvious win.=20
>>
>>
>> IOW:=20
>>
>> // implicit cting-dtor=20
>> foo::~foo(foo* new_foo) // or char* / void*=20
>> {=20
>> new (new_foo)(std::move(this));=20
>> this->~foo();=20
>> }=20
>>
>> // trivial cting-dtor=20
>> foo::~foo(foo* new_foo) // or char* / void*=20
>> {=20
>> memcpy(new_foo, this, sizeof(foo));=20
>> __builtin_create<foo>(new_foo); // bless new object as created=20
>> __builtin_release(this); // pedantic, probably no-op=20
>> }=20
>>
>> (I think having a concept of triviality of the cting-dtor might help=20
>> with some of the other examples you gave...)=20
>>
>> > To some extents these are concerns more on the feasibility of the=20
>> > implementation (optimizer) than the language itself, and it can be=20
>> argued=20
>> > that if a tag for the constructor, a wrapper=20
>> ('destructive_move_ref<T>()')=20
>> > or any other mechanism is standardized, compiler writers would have an=
=20
>> > incentive to work towards providing these optimizations.=20
>>
>> Yes. (And again, having triviality would enable the library to tackle=20
>> probably many of the most critical cases if the optimizer can't.)=20
>>
>> > Yet another concern is that the source object is left in an invalid=20
>> state,=20
>> > which opens the path for misuse=20
>>
>> If you implement this by cting-dtor, the source *has been destroyed*. So=
=20
>> while the above is true, it's no worse than:=20
>>
>> pfoo->~foo();=20
>> // referring again to pfoo at this point would be bad...=20
>>
>> The invocation would need to be something like:=20
>>
>> // allocate non-typed buffer e.g. using malloc=20
>> old_ptr->~T(new_ptr);=20
>> // *old_ptr is now destroyed, new_ptr is now a constructed T=20
>>
>> (And I believe the onus is already on the compiler to know that the=20
>> object is already destroyed if a dtor is explicitly called?)=20
>>
>> > for example the implementation of=20
>> > 'insert_impl' above could be attempted by a non-expert user as:=20
>> >=20
>> > vector<T>::insert_impl(iterator pos, T&& value, destructive_move_tag)=
=20
>> > T tmp(move(value));=20
>>
>> This can't work (i.e. can't use a cting-dtor); rvalue reference=20
>> semantics require that 'value' is left in a constructed (if unspecified)=
=20
>> state. Use emplace if you want to avoid the additional allocation.=20
>>
>> The only other way this could be solved is to invent a new indirection=
=20
>> type, probably '~', that says that the callee will destroy the object.=
=20
>>
>> Anyway, this isn't the major bottleneck, which is relocating a large=20
>> number of contiguous values e.g. when resizing an array.=20
>>
>> --=20
>> Matthew=20
>>
>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_86_2091785587.1438938239855
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>To avoid any issues with the=C2=A0<font face=3D"couri=
er new,monospace">memcpy/memmove</font> step (1) being separate from the ca=
ll-move-destructor step (2), we can make the compiler generate code that en=
capsulates this; similar in nature to how the keywords <font face=3D"courie=
r new,monospace">new</font> and <font face=3D"courier new,monospace">delete=
</font> work.</div><div><br></div><div>So, if we have an object with a move=
destructor:</div><div><br></div><div><font face=3D"courier new,monospace">=
<pre style=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);"><span =
style=3D"color: rgb(32, 0, 128); font-weight: bold;">class</span> StringTyp=
e <span style=3D"color: rgb(64, 96, 128);">{</span>
<span style=3D"color: rgb(48, 128, 128);">~</span>StringType<span style=
=3D"color: rgb(48, 128, 128);">(</span>StringType<span style=3D"color: rgb(=
48, 128, 128);">&</span> x<span style=3D"color: rgb(48, 128, 128);">)</=
span> <span style=3D"color: rgb(64, 96, 128);">{</span>
<span style=3D"color: rgb(89, 89, 121);">// x is already a bitwise copy=
of *this</span>
<span style=3D"color: rgb(89, 89, 121);">// perform patch-up of self-re=
ferences</span>
<span style=3D"color: rgb(64, 96, 128);">}</span>
<span style=3D"color: rgb(64, 96, 128);">}</span><span style=3D"color: rgb(=
64, 96, 128);">;</span>
</pre></font></div><div><br></div><div>The developer does not invoke this d=
irectly, but=C2=A0via a compiler-generated static destructor, declared like=
this:</div><div><br></div><div><font face=3D"courier new,monospace"><pre s=
tyle=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);">StringType<s=
pan style=3D"color: rgb(48, 128, 128);">*</span> StringType<span style=3D"c=
olor: rgb(64, 96, 128);">::</span><span style=3D"color: rgb(48, 128, 128);"=
>~</span>StringType<span style=3D"color: rgb(48, 128, 128);">(</span><span =
style=3D"color: rgb(32, 0, 128); font-weight: bold;">void</span><span style=
=3D"color: rgb(48, 128, 128);">*</span> d<span style=3D"color: rgb(48, 128,=
128);">,</span> StringType<span style=3D"color: rgb(48, 128, 128);">*</spa=
n> s<span style=3D"color: rgb(48, 128, 128);">,</span> <span style=3D"color=
: rgb(0, 102, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">::<=
/span><span style=3D"color: rgb(0, 48, 96);">size_t</span> n<span style=3D"=
color: rgb(48, 128, 128);">=3D</span><span style=3D"color: rgb(0, 140, 0);"=
>1</span><span style=3D"color: rgb(48, 128, 128);">)</span><span style=3D"c=
olor: rgb(64, 96, 128);">;</span>
</pre></font><br></div><div>When this is invoked, the=C2=A0<strong>compiler=
</strong> then generates the equivalent of this:</div><div><br></div><div><=
font face=3D"courier new,monospace"><pre style=3D"background: rgb(246, 248,=
255); color: rgb(0, 0, 32);"><span style=3D"color: rgb(0, 48, 96);">memmov=
e</span><span style=3D"color: rgb(48, 128, 128);">(</span>d<span style=3D"c=
olor: rgb(48, 128, 128);">,</span> s<span style=3D"color: rgb(48, 128, 128)=
;">,</span> n <span style=3D"color: rgb(48, 128, 128);">*</span> <span styl=
e=3D"color: rgb(32, 0, 128); font-weight: bold;">sizeof</span><span style=
=3D"color: rgb(48, 128, 128);">(</span>StringType<span style=3D"color: rgb(=
48, 128, 128);">)</span><span style=3D"color: rgb(48, 128, 128);">)</span><=
span style=3D"color: rgb(64, 96, 128);">;</span>
StringType<span style=3D"color: rgb(48, 128, 128);">*</span> dt <span style=
=3D"color: rgb(48, 128, 128);">=3D</span> <span style=3D"color: rgb(48, 128=
, 128);">(</span>StringType<span style=3D"color: rgb(48, 128, 128);">*</spa=
n><span style=3D"color: rgb(48, 128, 128);">)</span> d<span style=3D"color:=
rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">for</span> <span=
style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(0, 1=
02, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">::</span><spa=
n style=3D"color: rgb(0, 48, 96);">size_t</span> i<span style=3D"color: rgb=
(48, 128, 128);">=3D</span><span style=3D"color: rgb(0, 140, 0);">0</span><=
span style=3D"color: rgb(64, 96, 128);">;</span> i<span style=3D"color: rgb=
(48, 128, 128);">!</span><span style=3D"color: rgb(48, 128, 128);">=3D</spa=
n>n<span style=3D"color: rgb(64, 96, 128);">;</span> <span style=3D"color: =
rgb(48, 128, 128);">+</span><span style=3D"color: rgb(48, 128, 128);">+</sp=
an>i<span style=3D"color: rgb(48, 128, 128);">)</span>
s<span style=3D"color: rgb(48, 128, 128);">[</span>i<span style=3D"color:=
rgb(48, 128, 128);">]</span><span style=3D"color: rgb(48, 128, 128);">.</s=
pan><span style=3D"color: rgb(48, 128, 128);">~</span>StringType<span style=
=3D"color: rgb(48, 128, 128);">(</span>dt<span style=3D"color: rgb(48, 128,=
128);">[</span>i<span style=3D"color: rgb(48, 128, 128);">]</span><span st=
yle=3D"color: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(64, 96,=
128);">;</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">return</span> dt=
<span style=3D"color: rgb(64, 96, 128);">;</span>
</pre></font></div><div><br></div><div>For trivial types, and for types tha=
t are trivially relocatable (empty move destructors)=C2=A0-=C2=A0the <font =
face=3D"courier new,monospace">for</font> loop is simply optimized away.</d=
iv><div><br></div><div>For types that require patching-up during relocation=
, the <font face=3D"courier new,monospace">for</font> loop calls the move d=
estructors that take care of it.</div><div><br></div><div>But crucially -=
=C2=A0the developer does not perform these individual steps. The developer=
=C2=A0just calls:</div><div><br></div><div><font face=3D"courier new,monosp=
ace"><pre style=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);">S=
tringType<span style=3D"color: rgb(48, 128, 128);">*</span> dest <span styl=
e=3D"color: rgb(48, 128, 128);">=3D</span> StringType<span style=3D"color: =
rgb(64, 96, 128);">::</span><span style=3D"color: rgb(48, 128, 128);">~</sp=
an>StringType<span style=3D"color: rgb(48, 128, 128);">(</span>destptr<span=
style=3D"color: rgb(48, 128, 128);">,</span> src<span style=3D"color: rgb(=
48, 128, 128);">,</span> n<span style=3D"color: rgb(48, 128, 128);">)</span=
><span style=3D"color: rgb(64, 96, 128);">;</span>
</pre></font></div><div><br></div><div>This construction doesn't work w=
ith <font face=3D"courier new,monospace">realloc</font> - it requires simul=
taneous access to both old memory and new, which <font face=3D"courier new,=
monospace">realloc</font> does not provide - but some type of=C2=A0<font fa=
ce=3D"courier new,monospace">realloc_in_place_only</font> could be provided=
for this purpose.</div><div><br></div><div><br>On Friday, August 7, 2015 a=
t 2:00:59 AM UTC-6, isocp...@denisbider.com wrote:</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; bor=
der-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-sty=
le: solid;"><div dir=3D"ltr"><div>It would be nice if the move destructor d=
oes not expose too much of a "nuts and bolts" interface -=C2=A0su=
ch as requiring the developer to call placement new, explicitly call a dest=
ructor, and so forth.</div><div><br></div><div>What if the move destructor =
is called with an object reference that has ALREADY had memcpy performed, a=
nd is expected to simply perform a patch-up?</div><div><br></div><div>This =
way, if the move destructor does nothing, the object has been trivially mov=
ed. No additional code required.</div><div><br></div><div>If the move destr=
uctor is declared deleted, the object cannot be destructively moved.</div><=
div><br></div><div>The way an array of objects is moved could then consist =
of:</div><div><br></div><div>1. memcpy whole array of objects</div><div>2. =
call move destructors to perform any patch-ups</div><p><br></p><div>Static =
analysis tools would detect step (2) as transition of objects to new locati=
on.</div><div><br></div><div>No need to perform magic to consolidate the me=
mory copies, and=C2=A0static analysis works.</div><div><br><br>On Thursday,=
August 6, 2015 at 9:36:58 AM UTC-6, Matthew Woehlke wrote:</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1=
ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-l=
eft-style: solid;">On 2015-08-06 04:35, David Rodr=C3=ADguez Ibeas wrote:
<br>> I wasn't as much concerned with the destruction as the constru=
ction. The
<br>> question comes back again as of whether a compiler could be smart =
enough to
<br>> merge multiple 'memcpy', and while in the trivial case it =
would seem
<br>> reasonable, I fear the are some cases that are not so trivial in t=
he
<br>> presence of padding, for example.
<br>
<br>I think the 'constructing destructor' pattern, with ability to =
check for
<br>those being trivial, would solve this problem (as well as allowing
<br>cheaper relocations even for classes that are self-referencing). Users
<br>that care (e.g. containers) can check for defaulted 'constructing
<br>destructors' and explicitly do a memmove instead; no compiler cleve=
rness
<br>needed.
<br>
<br>It occurs to me that *ALL* classes should *have* a cting-dtor, but that
<br>the same is not necessarily trivial.
<br>
<br>The implicit behavior should be to move-construct the target and then
<br>destruct the object. The explicitly defaulted behavior should be a
<br>memberwise call to the cting-dtors of each member. A trivial cting-dtor
<br>(e.g. implicit for POD types) is a memcpy. The compiler should be able
<br>to combine multiple trivial cting-dtors in a compound object into one o=
r
<br>more memcpy's (e.g. could be more than one in case of a member with
<br>non-trivial cting-dtor in the middle of the compound type).
<br>
<br>This allows us to easily optimize the relocation operation for types
<br>that consist /mainly, but not entirely/ of trivially relocatable
<br>members. It also allows us to potentially relax the rules (either now,
<br>or at some future date) for when the implicit cting-dtor can be made
<br>trivial. This would allow for example 'struct Point { double x, y; =
};'
<br>to be given a trivial cting-dtor without having to explicitly declare a
<br>defaulted cting-dtor, which is an obvious win.
<br>
<br>
<br>IOW:
<br>
<br>=C2=A0 // implicit cting-dtor
<br>=C2=A0 foo::~foo(foo* new_foo) // or char* / void*
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 new (new_foo)(std::move(this));
<br>=C2=A0 =C2=A0 this->~foo();
<br>=C2=A0 }
<br>
<br>=C2=A0 // trivial cting-dtor
<br>=C2=A0 foo::~foo(foo* new_foo) // or char* / void*
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 memcpy(new_foo, this, sizeof(foo));
<br>=C2=A0 =C2=A0 __builtin_create<foo>(new_foo)<wbr>; // bless new o=
bject as created
<br>=C2=A0 =C2=A0 __builtin_release(this); // pedantic, probably no-op
<br>=C2=A0 }
<br>
<br>(I think having a concept of triviality of the cting-dtor might help
<br>with some of the other examples you gave...)
<br>
<br>> To some extents these are concerns more on the feasibility of the
<br>> implementation (optimizer) than the language itself, and it can be=
argued
<br>> that if a tag for the constructor, a wrapper ('destructive_mov=
e_ref<T>()')
<br>> or any other mechanism is standardized, compiler writers would hav=
e an
<br>> incentive to work towards providing these optimizations.
<br>
<br>Yes. (And again, having triviality would enable the library to tackle
<br>probably many of the most critical cases if the optimizer can't.)
<br>
<br>> Yet another concern is that the source object is left in an invali=
d state,
<br>> which opens the path for misuse
<br>
<br>If you implement this by cting-dtor, the source *has been destroyed*. S=
o
<br>while the above is true, it's no worse than:
<br>
<br>=C2=A0 pfoo->~foo();
<br>=C2=A0 // referring again to pfoo at this point would be bad...
<br>
<br>The invocation would need to be something like:
<br>
<br>=C2=A0 // allocate non-typed buffer e.g. using malloc
<br>=C2=A0 old_ptr->~T(new_ptr);
<br>=C2=A0 // *old_ptr is now destroyed, new_ptr is now a constructed T
<br>
<br>(And I believe the onus is already on the compiler to know that the
<br>object is already destroyed if a dtor is explicitly called?)
<br>
<br>> for example the implementation of
<br>> 'insert_impl' above could be attempted by a non-expert use=
r as:
<br>>=20
<br>> vector<T>::insert_impl(<wbr>iterator pos, T&& value,=
destructive_move_tag)
<br>> =C2=A0 =C2=A0T tmp(move(value));
<br>
<br>This can't work (i.e. can't use a cting-dtor); rvalue reference
<br>semantics require that 'value' is left in a constructed (if uns=
pecified)
<br>state. Use emplace if you want to avoid the additional allocation.
<br>
<br>The only other way this could be solved is to invent a new indirection
<br>type, probably '~', that says that the callee will destroy the =
object.
<br>
<br>Anyway, this isn't the major bottleneck, which is relocating a larg=
e
<br>number of contiguous values e.g. when resizing an array.
<br>
<br>--=20
<br>Matthew
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_86_2091785587.1438938239855--
------=_Part_85_488097591.1438938239854--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 07 Aug 2015 10:25:08 -0400
Raw View
On 2015-08-07 04:00, isocppgroup@denisbider.com wrote:
> It would be nice if the move destructor does not expose too much of a "nuts
> and bolts" interface - such as requiring the developer to call placement
> new, explicitly call a destructor, and so forth.
*Something* has to bless the new object as created, and the old object
as destroyed (that's the whole reason we're having so much discussion).
Note that you *aren't* required to use placement new. Rather, you have
the *option* to use placement new, as one way of initializing the new
object. I think this is a very good thing because it allows you to
control which ctor is used. Similarly, explicitly calling the dtor
allows you to control when - or *if* - it is called.
Note also that you are referring to the *default implicit* cting-dtor.
If you are writing your own, it is probably because you are doing
something special to construct the new object, and *need* that level of
control... and because you aren't actually going to call the old
object's dtor at all!
A better question is if the compiler should implicitly add the necessary
calls to "bless" the new object as created and the old object as
destroyed, regardless of what actually happens in the cting-dtor
(excepting perhaps that it throws, though of course a cting-dtor that
isn't nothrow is of limited value). Quite possibly "yes", especially as
those calls may not be portable. The only potential issue there is
ensuring we don't run into some odd trap with "twice blessing", but
since all of this is ultimately language-lawyering issues and not
anything that is a problem for actual current generated assembly, I
imagine we can work around that, if there is even a problem in the first
place.
> What if the move destructor is called with an object reference that has
> ALREADY had memcpy performed, and is expected to simply perform a patch-up?
This is not allowed. You must not use memcpy to relocate an object
unless its cting-dtor is trivial. If it isn't, you MUST actually call
the cting-dtor, and are not allowed to do anything outside of the same
to create or destroy the new/old objects.
At least that's my current take. It does slightly pessimize the
std::string case, though I'm not convinced the difference is that great.
(I'd also be concerned that the concept of a "patch up operator" runs
afoul of the same lifetime issues.)
I think it would be better to say that compilers should detect and
optimize the case of running a loop of cting-dtors over a contiguous
memory region where a) the cting-dtor is inline, b) the first thing the
cting-dtor does is memcpy the old object to the new, and c) the
cting-dtor does not access the old memory.
In fact, that last point is why I would be really nervous about a
patch-up operator; you'd have to pass it a (non-writable!) memory
address that contains memory in an undetermined state.
> If the move destructor is declared deleted, the object cannot be
> destructively moved.
My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
possible for any type with a move and/or copy ctor and an accessible
dtor. Deleting the cting-dtor would imply that the type lacks one or
more of those.
But... such a type would be unusable in e.g. a std::vector anyway... so
I suppose there is no harm. I would assert however that container
classes should refuse to instantiate for such a type, i.e. it is not
expected that a container class that *can* use a cting-dtor will or
should provide fallbacks for a type that explicitly deletes it.
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: isocppgroup@denisbider.com
Date: Fri, 7 Aug 2015 08:42:01 -0700 (PDT)
Raw View
------=_Part_2169_1759259554.1438962121680
Content-Type: multipart/alternative;
boundary="----=_Part_2170_245950472.1438962121685"
------=_Part_2170_245950472.1438962121685
Content-Type: text/plain; charset=UTF-8
> *Something* has to bless the new object as created, and the old
> object as destroyed (that's the whole reason we're having so
> much discussion).
See my last message for that:
StringType* StringType::~StringType(void* d, StringType* s, std::size_t n=1);
This would perform the destructive move of one or more objects as a
transaction, just like invoking keywords new or delete is a transaction.
It makes most sense to me that the implementation of this transactional
move concept performs the equivalent of memcpy for an object before calling
the move destructor. It makes things a lot simpler.
On Friday, August 7, 2015 at 8:25:22 AM UTC-6, Matthew Woehlke wrote:
> On 2015-08-07 04:00, isocp...@denisbider.com <javascript:> wrote:
> > It would be nice if the move destructor does not expose too much of a
> "nuts
> > and bolts" interface - such as requiring the developer to call placement
> > new, explicitly call a destructor, and so forth.
>
> *Something* has to bless the new object as created, and the old object
> as destroyed (that's the whole reason we're having so much discussion).
>
> Note that you *aren't* required to use placement new. Rather, you have
> the *option* to use placement new, as one way of initializing the new
> object. I think this is a very good thing because it allows you to
> control which ctor is used. Similarly, explicitly calling the dtor
> allows you to control when - or *if* - it is called.
>
> Note also that you are referring to the *default implicit* cting-dtor.
> If you are writing your own, it is probably because you are doing
> something special to construct the new object, and *need* that level of
> control... and because you aren't actually going to call the old
> object's dtor at all!
>
> A better question is if the compiler should implicitly add the necessary
> calls to "bless" the new object as created and the old object as
> destroyed, regardless of what actually happens in the cting-dtor
> (excepting perhaps that it throws, though of course a cting-dtor that
> isn't nothrow is of limited value). Quite possibly "yes", especially as
> those calls may not be portable. The only potential issue there is
> ensuring we don't run into some odd trap with "twice blessing", but
> since all of this is ultimately language-lawyering issues and not
> anything that is a problem for actual current generated assembly, I
> imagine we can work around that, if there is even a problem in the first
> place.
>
> > What if the move destructor is called with an object reference that has
> > ALREADY had memcpy performed, and is expected to simply perform a
> patch-up?
>
> This is not allowed. You must not use memcpy to relocate an object
> unless its cting-dtor is trivial. If it isn't, you MUST actually call
> the cting-dtor, and are not allowed to do anything outside of the same
> to create or destroy the new/old objects.
>
> At least that's my current take. It does slightly pessimize the
> std::string case, though I'm not convinced the difference is that great.
>
> (I'd also be concerned that the concept of a "patch up operator" runs
> afoul of the same lifetime issues.)
>
> I think it would be better to say that compilers should detect and
> optimize the case of running a loop of cting-dtors over a contiguous
> memory region where a) the cting-dtor is inline, b) the first thing the
> cting-dtor does is memcpy the old object to the new, and c) the
> cting-dtor does not access the old memory.
>
> In fact, that last point is why I would be really nervous about a
> patch-up operator; you'd have to pass it a (non-writable!) memory
> address that contains memory in an undetermined state.
>
> > If the move destructor is declared deleted, the object cannot be
> > destructively moved.
>
> My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
> possible for any type with a move and/or copy ctor and an accessible
> dtor. Deleting the cting-dtor would imply that the type lacks one or
> more of those.
>
> But... such a type would be unusable in e.g. a std::vector anyway... so
> I suppose there is no harm. I would assert however that container
> classes should refuse to instantiate for such a type, i.e. it is not
> expected that a container class that *can* use a cting-dtor will or
> should provide fallbacks for a type that explicitly deletes it.
>
> --
> Matthew
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2170_245950472.1438962121685
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> *Something* has to bless the new object as creat=
ed, and the old</div><div>> object as destroyed (that's the whole re=
ason we're having so</div><div>> much discussion). </div><div><br></=
div><div>See my last message for that:</div><div><br></div><div><pre style=
=3D"background: rgb(246, 248, 255); color: rgb(0, 0, 32);">StringType<span =
style=3D"color: rgb(48, 128, 128);">*</span> StringType<span style=3D"color=
: rgb(64, 96, 128);">::</span><span style=3D"color: rgb(48, 128, 128);">~</=
span>StringType<span style=3D"color: rgb(48, 128, 128);">(</span><span styl=
e=3D"color: rgb(32, 0, 128); font-weight: bold;">void</span><span style=3D"=
color: rgb(48, 128, 128);">*</span> d<span style=3D"color: rgb(48, 128, 128=
);">,</span> StringType<span style=3D"color: rgb(48, 128, 128);">*</span> s=
<span style=3D"color: rgb(48, 128, 128);">,</span> <span style=3D"color: rg=
b(0, 102, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">::</spa=
n><span style=3D"color: rgb(0, 48, 96);">size_t</span> n<span style=3D"colo=
r: rgb(48, 128, 128);">=3D</span><span style=3D"color: rgb(0, 140, 0);">1</=
span><span style=3D"color: rgb(48, 128, 128);">)</span><span style=3D"color=
: rgb(64, 96, 128);">;</span>
</pre></div><div><br></div><div>This would perform the destructive move of =
one or more objects as a transaction, just like invoking keywords <font fac=
e=3D"courier new,monospace">new</font> or <font face=3D"courier new,monospa=
ce">delete</font> is a transaction.</div><div><br></div><div>It makes most =
sense to me that the implementation of this transactional move concept perf=
orms the equivalent of <font face=3D"courier new,monospace">memcpy</font> f=
or an object before calling the move destructor. It makes things=C2=A0a lot=
simpler.</div><div><br></div><div><br>On Friday, August 7, 2015 at 8:25:22=
AM UTC-6, Matthew Woehlke wrote:</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb=
(204, 204, 204); border-left-width: 1px; border-left-style: solid;">On 2015=
-08-07 04:00, <a onmousedown=3D"this.href=3D'javascript:';return tr=
ue;" onclick=3D"this.href=3D'javascript:';return true;" href=3D"jav=
ascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"EphLA=
8HREAAJ">isocp...@denisbider.com</a> wrote:
<br>> It would be nice if the move destructor does not expose too much o=
f a "nuts=20
<br>> and bolts" interface - such as requiring the developer to cal=
l placement=20
<br>> new, explicitly call a destructor, and so forth.
<br>
<br>*Something* has to bless the new object as created, and the old object
<br>as destroyed (that's the whole reason we're having so much disc=
ussion).
<br>
<br>Note that you *aren't* required to use placement new. Rather, you h=
ave
<br>the *option* to use placement new, as one way of initializing the new
<br>object. I think this is a very good thing because it allows you to
<br>control which ctor is used. Similarly, explicitly calling the dtor
<br>allows you to control when - or *if* - it is called.
<br>
<br>Note also that you are referring to the *default implicit* cting-dtor.
<br>If you are writing your own, it is probably because you are doing
<br>something special to construct the new object, and *need* that level of
<br>control... and because you aren't actually going to call the old
<br>object's dtor at all!
<br>
<br>A better question is if the compiler should implicitly add the necessar=
y
<br>calls to "bless" the new object as created and the old object=
as
<br>destroyed, regardless of what actually happens in the cting-dtor
<br>(excepting perhaps that it throws, though of course a cting-dtor that
<br>isn't nothrow is of limited value). Quite possibly "yes",=
especially as
<br>those calls may not be portable. The only potential issue there is
<br>ensuring we don't run into some odd trap with "twice blessing&=
quot;, but
<br>since all of this is ultimately language-lawyering issues and not
<br>anything that is a problem for actual current generated assembly, I
<br>imagine we can work around that, if there is even a problem in the firs=
t
<br>place.
<br>
<br>> What if the move destructor is called with an object reference tha=
t has=20
<br>> ALREADY had memcpy performed, and is expected to simply perform a =
patch-up?
<br>
<br>This is not allowed. You must not use memcpy to relocate an object
<br>unless its cting-dtor is trivial. If it isn't, you MUST actually ca=
ll
<br>the cting-dtor, and are not allowed to do anything outside of the same
<br>to create or destroy the new/old objects.
<br>
<br>At least that's my current take. It does slightly pessimize the
<br>std::string case, though I'm not convinced the difference is that g=
reat.
<br>
<br>(I'd also be concerned that the concept of a "patch up operato=
r" runs
<br>afoul of the same lifetime issues.)
<br>
<br>I think it would be better to say that compilers should detect and
<br>optimize the case of running a loop of cting-dtors over a contiguous
<br>memory region where a) the cting-dtor is inline, b) the first thing the
<br>cting-dtor does is memcpy the old object to the new, and c) the
<br>cting-dtor does not access the old memory.
<br>
<br>In fact, that last point is why I would be really nervous about a
<br>patch-up operator; you'd have to pass it a (non-writable!) memory
<br>address that contains memory in an undetermined state.
<br>
<br>> If the move destructor is declared deleted, the object cannot be=
=20
<br>> destructively moved.
<br>
<br>My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
<br>possible for any type with a move and/or copy ctor and an accessible
<br>dtor. Deleting the cting-dtor would imply that the type lacks one or
<br>more of those.
<br>
<br>But... such a type would be unusable in e.g. a std::vector anyway... so
<br>I suppose there is no harm. I would assert however that container
<br>classes should refuse to instantiate for such a type, i.e. it is not
<br>expected that a container class that *can* use a cting-dtor will or
<br>should provide fallbacks for a type that explicitly deletes it.
<br>
<br>--=20
<br>Matthew
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2170_245950472.1438962121685--
------=_Part_2169_1759259554.1438962121680--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Fri, 7 Aug 2015 16:53:08 +0100
Raw View
--089e010d89dada7be3051cbaa157
Content-Type: text/plain; charset=UTF-8
On Fri, Aug 7, 2015 at 4:42 PM, <isocppgroup@denisbider.com> wrote:
> > *Something* has to bless the new object as created, and the old
> > object as destroyed (that's the whole reason we're having so
> > much discussion).
>
> See my last message for that:
>
> StringType* StringType::~StringType(void* d, StringType* s, std::size_t n=1);
>
> This would perform the destructive move of one or more objects as a
> transaction, just like invoking keywords new or delete is a transaction.
>
> It makes most sense to me that the implementation of this transactional
> move concept performs the equivalent of memcpy for an object before
> calling the move destructor. It makes things a lot simpler.
>
How does that deal with composition? Unless otherwise specified each base
and member should be destructively move constructed from the corresponding
entity in the source; or at least there needs to be a mem-initializer-list
style syntax so that the compiler can check that each base and member is
dealt with. Adding a std::string member to a class should not result in UB.
> > What if the move destructor is called with an object reference that has
>> > ALREADY had memcpy performed, and is expected to simply perform a
>> patch-up?
>>
>> This is not allowed. You must not use memcpy to relocate an object
>> unless its cting-dtor is trivial. If it isn't, you MUST actually call
>> the cting-dtor, and are not allowed to do anything outside of the same
>> to create or destroy the new/old objects.
>>
>
Absolutely. I think the great thing about this is that having a trivial
cting-dtor is precisely the semantics necessary to say that a type can be
destructively moved via memcpy; and with appropriate lawyering aggregates
get their trivial cting-dtor for free.
> If the move destructor is declared deleted, the object cannot be
>> > destructively moved.
>>
>> My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
>> possible for any type with a move and/or copy ctor and an accessible
>> dtor. Deleting the cting-dtor would imply that the type lacks one or
>> more of those.
>>
>
That depends on what the implicit behavior might be. If the implicit
cting-dtor were to perform memberwise destructive move, declaring it
deleted would be the instruction to fall back to move/copy + destruct.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e010d89dada7be3051cbaa157
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On F=
ri, Aug 7, 2015 at 4:42 PM, <span dir=3D"ltr"><<a href=3D"mailto:isocpp=
group@denisbider.com" target=3D"_blank">isocppgroup@denisbider.com</a>><=
/span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span clas=
s=3D""><div>> *Something* has to bless the new object as created, and th=
e old</div><div>> object as destroyed (that's the whole reason we=
9;re having so</div><div>> much discussion). </div><div><br></div></span=
><div>See my last message for that:</div><div><pre style=3D"background:rgb(=
246,248,255);color:rgb(0,0,32)">StringType<span style=3D"color:rgb(48,128,1=
28)">*</span> StringType<span style=3D"color:rgb(64,96,128)">::</span><span=
style=3D"color:rgb(48,128,128)">~</span>StringType<span style=3D"color:rgb=
(48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">=
void</span><span style=3D"color:rgb(48,128,128)">*</span> d<span style=3D"c=
olor:rgb(48,128,128)">,</span> StringType<span style=3D"color:rgb(48,128,12=
8)">*</span> s<span style=3D"color:rgb(48,128,128)">,</span> <span style=3D=
"color:rgb(0,102,238)">std</span><span style=3D"color:rgb(64,96,128)">::</s=
pan><span style=3D"color:rgb(0,48,96)">size_t</span> n<span style=3D"color:=
rgb(48,128,128)">=3D</span><span style=3D"color:rgb(0,140,0)">1</span><span=
style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,128=
)">;</span>
</pre></div><div>This would perform the destructive move of one or more obj=
ects as a transaction, just like invoking keywords <font face=3D"courier ne=
w,monospace">new</font> or <font face=3D"courier new,monospace">delete</fon=
t> is a transaction.</div><div><br></div><div>It makes most sense to me tha=
t the implementation of this transactional move concept performs the equiva=
lent of <font face=3D"courier new,monospace">memcpy</font> for an object be=
fore calling the move destructor. It makes things=C2=A0a lot simpler.</div>=
</div></blockquote><div><br></div><div>How does that deal with composition?=
Unless otherwise specified each base and member should be destructively mo=
ve constructed from the corresponding entity in the source; or at least the=
re needs to be a mem-initializer-list style syntax so that the compiler can=
check that each base and member is dealt with. Adding a std::string member=
to a class should not result in UB.</div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div><div class=3D"h5"><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-lef=
t-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">>=
; What if the move destructor is called with an object reference that has=
=20
<br>> ALREADY had memcpy performed, and is expected to simply perform a =
patch-up?
<br>
<br>This is not allowed. You must not use memcpy to relocate an object
<br>unless its cting-dtor is trivial. If it isn't, you MUST actually ca=
ll
<br>the cting-dtor, and are not allowed to do anything outside of the same
<br>to create or destroy the new/old objects.=C2=A0<br></blockquote></div><=
/div></div></blockquote><div>=C2=A0</div><div><div>Absolutely. I think the =
great thing about this is that having a trivial cting-dtor is precisely the=
semantics necessary to say that a type can be destructively moved via memc=
py; and with appropriate lawyering aggregates get their trivial cting-dtor =
for free.</div></div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div><div class=3D"h5"><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204=
);border-left-width:1px;border-left-style:solid">> If the move destructo=
r is declared deleted, the object cannot be=20
<br>> destructively moved.
<br>
<br>My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
<br>possible for any type with a move and/or copy ctor and an accessible
<br>dtor. Deleting the cting-dtor would imply that the type lacks one or
<br>more of those.=C2=A0<br></blockquote></div></div></div></blockquote><di=
v><br></div><div>That depends on what the implicit behavior might be. If th=
e implicit cting-dtor were to perform memberwise destructive move, declarin=
g it deleted would be the instruction to fall back to move/copy + destruct.=
=C2=A0</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e010d89dada7be3051cbaa157--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 07 Aug 2015 12:07:41 -0400
Raw View
On 2015-08-07 11:42, isocppgroup@denisbider.com wrote:
> StringType* StringType::~StringType(void* d, StringType* s, std::size_t n=1);
>
> This would perform the destructive move of one or more objects as a
> transaction, just like invoking keywords new or delete is a transaction.
The "one *or more*" (emphasis added) part would be a significant
departure from the current language rules. I'm having a hard time seeing
the justification.
The closest we have currently is delete[], which still calls each
object's dtor individually.
If nothing else, 'this' makes no sense in such a context, i.e. you are
at least missing a 'static'.
> It makes most sense to me that the implementation of this transactional
> move concept performs the equivalent of memcpy for an object before calling
> the move destructor. It makes things a lot simpler.
....and far less generic.
What if doing a memcpy is *wrong*? Now you've wasted a bunch of work
copying data that isn't useful.
Having something like a cting-dtor has obvious benefit (don't waste work
maintaining the old object in a valid state when it's about to be
destroyed anyway). Having a cting-dtor *that can be trivial* has
*enormous* obvious value; many, many objects can be trivially
"relocated"... and indeed libraries already do this despite that it is
UB; having a way to "bless" such operation has obvious benefit.
I'm less convinced that there is significant benefit to optimizing
corner cases. The *only* benefit, AFAICT, to e.g. the std::string case
is merging the memcpy's for an array of such objects into a larger memcpy.
Do you have benchmarks showing that this is a significant improvement?
Keep in mind that the small memcpy will most likely be inlined, and that
there is at least a branch per object in either case in addition to
whatever memcpy(s) happen. (If the patch-up operator isn't inlined,
that's probably going to swamp the memcpy(s).)
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 07 Aug 2015 12:28:13 -0400
Raw View
On 2015-08-07 11:53, Edward Catmur wrote:
> I think the great thing about [cting-dtors] is that having a trivial
> cting-dtor is precisely the semantics necessary to say that a type can be
> destructively moved via memcpy; and with appropriate lawyering aggregates
> get their trivial cting-dtor for free.
Exactly ;-).
> On 2015-08-07 10:25, Matthew Woehlke wrote:
>> On 2015-08-07 04:00, isocppgroup@denisbider.com wrote:
>>> If the move destructor is declared deleted, the object cannot be
>>> destructively moved.
>>
>> My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
>> possible for any type with a move and/or copy ctor and an accessible
>> dtor. Deleting the cting-dtor would imply that the type lacks one or
>> more of those.
(Note: my follow up comment, which Edward did not quote, was to allow
deleting the cting-dtor. I can't imagine a case where doing so is useful
- the cases where the operation is not possible should result in it
already being implicitly deleted - except maybe for improving
diagnostics, but I don't see any particular reason to forbid doing so.)
> That depends on what the implicit behavior might be. If the implicit
> cting-dtor were to perform memberwise destructive move, declaring it
> deleted would be the instruction to fall back to move/copy + destruct.
Please re-read my message :-). I clearly stated that the *implicit*
behavior is to do a move/copy + regular destruct. (Which... may still be
trivial, i.e. if the ctors and regular dtor are trivial and all members'
cting-dtors are trivial.)
The *(explicitly) defaulted* cting-dtor calls the cting-dtors for each
member. IOW, explicitly declaring the cting-dtor '= default' is telling
the compiler that even though the ctors and/or regular dtor may be
non-trivial, that the object can be relocated in said manner (i.e. the
ctors / regular dtor can be skipped).
If the cting-dtor is deleted, you can't use it. Period. It should never
be deleted, however, unless the implicit implementation is impossible,
i.e. the dtor is protected, and/or there is no public move/copy ctor. As
noted above, this should already result in it being implicitly deleted
due to the implicit implementation being ill-formed. So the only benefit
I can think of to explicitly deleting a cting-dtor is to get a more
concise error message if someone tries to use it ("is deleted" vs. "is
implicitly deleted because...").
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Fri, 7 Aug 2015 17:49:37 +0100
Raw View
--089e01228c40deb192051cbb6b58
Content-Type: text/plain; charset=UTF-8
Ah; I see what you mean now.
I think my confusion is due to the fact that it's a novelty to have =
default mean something different to the implicit behavior; for the other
special functions an explicitly-defaulted declaration has the effect of
restoring the (suppressed) special function of that signature, with the
same behavior it would have were it not suppressed. That seems something of
a gotcha; it certainly got me.
I may have missed it above, but what is your reasoning for having the
implicit behavior perform move/copy+destruct rather than memberwise
destructive move? If it's safety, that could be handled by having the
implicit behavior predicated on the presence of a user-defined dtor or
copy/move ctor/assign, on the reasonable assumption that anything that is
location-aware (above its members) would have at least one of those special
functions user-defined.
On Fri, Aug 7, 2015 at 5:28 PM, Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 2015-08-07 11:53, Edward Catmur wrote:
> > I think the great thing about [cting-dtors] is that having a trivial
> > cting-dtor is precisely the semantics necessary to say that a type can be
> > destructively moved via memcpy; and with appropriate lawyering aggregates
> > get their trivial cting-dtor for free.
>
> Exactly ;-).
>
> > On 2015-08-07 10:25, Matthew Woehlke wrote:
> >> On 2015-08-07 04:00, isocppgroup@denisbider.com wrote:
> >>> If the move destructor is declared deleted, the object cannot be
> >>> destructively moved.
> >>
> >> My knee-jerk reaction is to forbid that, as the implicit cting-dtor is
> >> possible for any type with a move and/or copy ctor and an accessible
> >> dtor. Deleting the cting-dtor would imply that the type lacks one or
> >> more of those.
>
> (Note: my follow up comment, which Edward did not quote, was to allow
> deleting the cting-dtor. I can't imagine a case where doing so is useful
> - the cases where the operation is not possible should result in it
> already being implicitly deleted - except maybe for improving
> diagnostics, but I don't see any particular reason to forbid doing so.)
>
> > That depends on what the implicit behavior might be. If the implicit
> > cting-dtor were to perform memberwise destructive move, declaring it
> > deleted would be the instruction to fall back to move/copy + destruct.
>
> Please re-read my message :-). I clearly stated that the *implicit*
> behavior is to do a move/copy + regular destruct. (Which... may still be
> trivial, i.e. if the ctors and regular dtor are trivial and all members'
> cting-dtors are trivial.)
>
> The *(explicitly) defaulted* cting-dtor calls the cting-dtors for each
> member. IOW, explicitly declaring the cting-dtor '= default' is telling
> the compiler that even though the ctors and/or regular dtor may be
> non-trivial, that the object can be relocated in said manner (i.e. the
> ctors / regular dtor can be skipped).
>
> If the cting-dtor is deleted, you can't use it. Period. It should never
> be deleted, however, unless the implicit implementation is impossible,
> i.e. the dtor is protected, and/or there is no public move/copy ctor. As
> noted above, this should already result in it being implicitly deleted
> due to the implicit implementation being ill-formed. So the only benefit
> I can think of to explicitly deleting a cting-dtor is to get a more
> concise error message if someone tries to use it ("is deleted" vs. "is
> implicitly deleted because...").
>
> --
> Matthew
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/f1zaOjyUem0/unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01228c40deb192051cbb6b58
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Ah; I see what you mean now.<div><br></div><div>I think my=
confusion is due to the fact that it's a novelty to have =3D default m=
ean something different to the implicit behavior; for the other special fun=
ctions an explicitly-defaulted declaration has the effect of restoring the =
(suppressed) special function of that signature, with the same behavior it =
would have were it not suppressed. That seems something of a gotcha; it cer=
tainly got me.</div><div><br></div><div>I may have missed it above, but wha=
t is your reasoning for having the implicit behavior perform move/copy+dest=
ruct rather than memberwise destructive move? If it's safety, that coul=
d be handled by having the implicit behavior predicated on the presence of =
a user-defined dtor or copy/move ctor/assign, on the reasonable assumption =
that anything that is location-aware (above its members) would have at leas=
t one of those special functions user-defined.</div><div><br></div></div><d=
iv class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Fri, Aug 7, 2015=
at 5:28 PM, Matthew Woehlke <span dir=3D"ltr"><<a href=3D"mailto:mwoehl=
ke.floss@gmail.com" target=3D"_blank">mwoehlke.floss@gmail.com</a>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex">On 2015-08-07 11:53, Edward Cat=
mur wrote:<br>
> I think the great thing about [cting-dtors] is that having a trivial<b=
r>
> cting-dtor is precisely the semantics necessary to say that a type can=
be<br>
> destructively moved via memcpy; and with appropriate lawyering aggrega=
tes<br>
> get their trivial cting-dtor for free.<br>
<br>
Exactly ;-).<br>
<br>
> On 2015-08-07 10:25, Matthew Woehlke wrote:<br>
>> On 2015-08-07 04:00, <a href=3D"mailto:isocppgroup@denisbider.com"=
>isocppgroup@denisbider.com</a> wrote:<br>
>>> If the move destructor is declared deleted, the object cannot =
be<br>
>>> destructively moved.<br>
>><br>
>> My knee-jerk reaction is to forbid that, as the implicit cting-dto=
r is<br>
>> possible for any type with a move and/or copy ctor and an accessib=
le<br>
>> dtor. Deleting the cting-dtor would imply that the type lacks one =
or<br>
>> more of those.<br>
<br>
(Note: my follow up comment, which Edward did not quote, was to allow<br>
deleting the cting-dtor. I can't imagine a case where doing so is usefu=
l<br>
- the cases where the operation is not possible should result in it<br>
already being implicitly deleted - except maybe for improving<br>
diagnostics, but I don't see any particular reason to forbid doing so.)=
<br>
<br>
> That depends on what the implicit behavior might be. If the implicit<b=
r>
> cting-dtor were to perform memberwise destructive move, declaring it<b=
r>
> deleted would be the instruction to fall back to move/copy + destruct.=
<br>
<br>
Please re-read my message :-). I clearly stated that the *implicit*<br>
behavior is to do a move/copy + regular destruct. (Which... may still be<br=
>
trivial, i.e. if the ctors and regular dtor are trivial and all members'=
;<br>
cting-dtors are trivial.)<br>
<br>
The *(explicitly) defaulted* cting-dtor calls the cting-dtors for each<br>
member. IOW, explicitly declaring the cting-dtor '=3D default' is t=
elling<br>
the compiler that even though the ctors and/or regular dtor may be<br>
non-trivial, that the object can be relocated in said manner (i.e. the<br>
ctors / regular dtor can be skipped).<br>
<br>
If the cting-dtor is deleted, you can't use it. Period. It should never=
<br>
be deleted, however, unless the implicit implementation is impossible,<br>
i.e. the dtor is protected, and/or there is no public move/copy ctor. As<br=
>
noted above, this should already result in it being implicitly deleted<br>
due to the implicit implementation being ill-formed. So the only benefit<br=
>
I can think of to explicitly deleting a cting-dtor is to get a more<br>
concise error message if someone tries to use it ("is deleted" vs=
.. "is<br>
implicitly deleted because...").<br>
<span class=3D"HOEnZb"><font color=3D"#888888"><br>
--<br>
Matthew<br>
<br>
--<br>
<br>
---<br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/f1zaOjyUem0/unsubscribe" rel=3D"noreferr=
er" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/f1zaOjyUem0/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-proposals+unsubscrib=
e@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01228c40deb192051cbb6b58--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 07 Aug 2015 13:36:20 -0400
Raw View
On 2015-08-07 12:49, Edward Catmur wrote:
> Ah; I see what you mean now.
>=20
> I think my confusion is due to the fact that it's a novelty to have =3D
> default mean something different to the implicit behavior; for the other
> special functions an explicitly-defaulted declaration has the effect of
> restoring the (suppressed) special function of that signature, with the
> same behavior it would have were it not suppressed. That seems something =
of
> a gotcha; it certainly got me.
That's a fair point. OTOH I can claim that that's a naming bikeshed :-).
IMO the implicit behavior should definitely be the boring behavior, i.e.
invoke a copy/move ctor and the regular dtor. There should also be a
concise way to specify calling the cting-dtors of all members without
calling the class's own ctor (any) or (regular) dtor. I used '=3D default'
for that, but it could be something else.
An example would be std::unique_ptr; it has non-trivial move ctor and
dtor, but the cting-dtor can be trivial. The compiler may not be able to
infer this=C2=B9, so a straight forward way to declare it as just doing
cting-dtor(s) on the member(s) is desired. (And when the member
cting-dtor(s) are trivial, the class's cting-dtor will also be trivial.
But we'd also still get correct behavior if they weren't.)
(=C2=B9 In the specific case of std::unique_ptr, with everything inlined,
it's actually not all *that* far-fetched that the compiler might be able
to infer that the cting-dtor is trivial, even without being so marked,
but that won't always be the case.)
> I may have missed it above, but what is your reasoning for having the
> implicit behavior perform move/copy+destruct rather than memberwise
> destructive move? If it's safety, that could be handled by having the
> implicit behavior predicated on the presence of a user-defined dtor or
> copy/move ctor/assign, on the reasonable assumption that anything that is
> location-aware (above its members) would have at least one of those speci=
al
> functions user-defined.
It is (for safety). If the ctor(s)/dtor are non-trivial, the implicit
behavior should not be allowed to skip them. The "normative" behavior
therefore should be move/copy ctor + regular dtor.
Note that I *did* say that the implicit behavior can be "trivial", in
which case despite the "normative" specification, the cting-dtor does in
fact 'degenerate' into a memcpy.
Basically, what that amounts to is there is *always* a cting-dtor unless
it is deleted (implicitly or explicitly), with the implicit behavior
always being The Right Thing=E2=84=A2, but also being efficient when it is
provably correct to do so.
I think where we're actually debating is on the implicit behavior being
memberwise copy/move followed by memberwise destroy vs. memberwise
cting-dtor. Those *should* be the same thing, unless there are
order-dependent side effects. Even so, I can probably live with that;
I'm just approaching the problem from something of an "as if" angle
starting from the safest thing to do, while you're fully chasing down
possible optimizations.
--=20
Matthew
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Fri, 7 Aug 2015 19:30:42 +0100
Raw View
--047d7b6222e458598c051cbcd5af
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
If the ctor(s) and dtor are non-user-defined (defaulted or declared as
defaulted) then the user has chosen to defer responsibility for copy/move
operations to the bases and members, so why not let the bases and members
decide? There's no user-written code being skipped.
I really don't want to have to teach beginning programmers that they have
to add some weird incantation to their aggregates to attain the full
performance of the library types. I also don't want to have to go over my
codebase, adding default cting-dtor to my aggregates; when move
constructors were added for C++11, user-defined aggregates benefited even
if they were originally written under C++03.
Finally, requiring explicit opt-in is dangerous! If a class evolves to
become location-aware then the maintainer adding the move ctor may well
miss the presence of the defaulted cting-dtor. If the implicit behavior is
OTOH dependent on the presence/absence of the other special functions then
it will gracefully and automatically change from memberwise destructive
move to move ctor + dtor, as the added move ctor suppresses the implicit
(memberwise destructive) cting-dtor.
On Fri, Aug 7, 2015 at 6:36 PM, Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 2015-08-07 12:49, Edward Catmur wrote:
> > Ah; I see what you mean now.
> >
> > I think my confusion is due to the fact that it's a novelty to have =3D
> > default mean something different to the implicit behavior; for the othe=
r
> > special functions an explicitly-defaulted declaration has the effect of
> > restoring the (suppressed) special function of that signature, with the
> > same behavior it would have were it not suppressed. That seems somethin=
g
> of
> > a gotcha; it certainly got me.
>
> That's a fair point. OTOH I can claim that that's a naming bikeshed :-).
> IMO the implicit behavior should definitely be the boring behavior, i.e.
> invoke a copy/move ctor and the regular dtor. There should also be a
> concise way to specify calling the cting-dtors of all members without
> calling the class's own ctor (any) or (regular) dtor. I used '=3D default=
'
> for that, but it could be something else.
>
> An example would be std::unique_ptr; it has non-trivial move ctor and
> dtor, but the cting-dtor can be trivial. The compiler may not be able to
> infer this=C2=B9, so a straight forward way to declare it as just doing
> cting-dtor(s) on the member(s) is desired. (And when the member
> cting-dtor(s) are trivial, the class's cting-dtor will also be trivial.
> But we'd also still get correct behavior if they weren't.)
>
> (=C2=B9 In the specific case of std::unique_ptr, with everything inlined,
> it's actually not all *that* far-fetched that the compiler might be able
> to infer that the cting-dtor is trivial, even without being so marked,
> but that won't always be the case.)
>
> > I may have missed it above, but what is your reasoning for having the
> > implicit behavior perform move/copy+destruct rather than memberwise
> > destructive move? If it's safety, that could be handled by having the
> > implicit behavior predicated on the presence of a user-defined dtor or
> > copy/move ctor/assign, on the reasonable assumption that anything that =
is
> > location-aware (above its members) would have at least one of those
> special
> > functions user-defined.
>
> It is (for safety). If the ctor(s)/dtor are non-trivial, the implicit
> behavior should not be allowed to skip them. The "normative" behavior
> therefore should be move/copy ctor + regular dtor.
>
> Note that I *did* say that the implicit behavior can be "trivial", in
> which case despite the "normative" specification, the cting-dtor does in
> fact 'degenerate' into a memcpy.
>
> Basically, what that amounts to is there is *always* a cting-dtor unless
> it is deleted (implicitly or explicitly), with the implicit behavior
> always being The Right Thing=E2=84=A2, but also being efficient when it i=
s
> provably correct to do so.
>
> I think where we're actually debating is on the implicit behavior being
> memberwise copy/move followed by memberwise destroy vs. memberwise
> cting-dtor. Those *should* be the same thing, unless there are
> order-dependent side effects. Even so, I can probably live with that;
> I'm just approaching the problem from something of an "as if" angle
> starting from the safest thing to do, while you're fully chasing down
> possible optimizations.
>
> --
> Matthew
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/f1zaOjyUem0/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--047d7b6222e458598c051cbcd5af
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>If the=C2=A0<span style=3D"font-size:12.8000001907349=
px">ctor(s) and dtor are non-user-defined (defaulted or declared as default=
ed) then the user has chosen to defer responsibility for copy/move operatio=
ns to the bases and members, so why not let the bases and members decide? T=
here's no user-written code being skipped.</span><br></div><div class=
=3D"gmail_extra"><br></div><div class=3D"gmail_extra">I really don't wa=
nt to have to teach beginning programmers that they have to add some weird =
incantation to their aggregates to attain the full performance of the libra=
ry types. I also don't want to have to go over my codebase, adding defa=
ult cting-dtor to my aggregates; when move constructors were added for C++1=
1, user-defined aggregates benefited even if they were originally written u=
nder C++03.</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_e=
xtra">Finally, requiring explicit opt-in is dangerous! If a class evolves t=
o become location-aware then the maintainer adding the move ctor may well m=
iss the presence of the defaulted cting-dtor. If the implicit behavior is O=
TOH dependent on the presence/absence of the other special functions then i=
t will gracefully and automatically change from memberwise destructive move=
to move ctor + dtor, as the added move ctor suppresses the implicit (membe=
rwise destructive) cting-dtor.</div><div class=3D"gmail_extra"><br></div><d=
iv class=3D"gmail_extra"><div class=3D"gmail_quote">On Fri, Aug 7, 2015 at =
6:36 PM, Matthew Woehlke <span dir=3D"ltr"><<a href=3D"mailto:mwoehlke.f=
loss@gmail.com" target=3D"_blank">mwoehlke.floss@gmail.com</a>></span> w=
rote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex">On 2015-08-07 12:49, Edward Catmur =
wrote:<br>
> Ah; I see what you mean now.<br>
><br>
> I think my confusion is due to the fact that it's a novelty to hav=
e =3D<br>
> default mean something different to the implicit behavior; for the oth=
er<br>
> special functions an explicitly-defaulted declaration has the effect o=
f<br>
> restoring the (suppressed) special function of that signature, with th=
e<br>
> same behavior it would have were it not suppressed. That seems somethi=
ng of<br>
> a gotcha; it certainly got me.<br>
<br>
That's a fair point. OTOH I can claim that that's a naming bikeshed=
:-).<br>
IMO the implicit behavior should definitely be the boring behavior, i.e.<br=
>
invoke a copy/move ctor and the regular dtor. There should also be a<br>
concise way to specify calling the cting-dtors of all members without<br>
calling the class's own ctor (any) or (regular) dtor. I used '=3D d=
efault'<br>
for that, but it could be something else.<br>
<br>
An example would be std::unique_ptr; it has non-trivial move ctor and<br>
dtor, but the cting-dtor can be trivial. The compiler may not be able to<br=
>
infer this=C2=B9, so a straight forward way to declare it as just doing<br>
cting-dtor(s) on the member(s) is desired. (And when the member<br>
cting-dtor(s) are trivial, the class's cting-dtor will also be trivial.=
<br>
But we'd also still get correct behavior if they weren't.)<br>
<br>
(=C2=B9 In the specific case of std::unique_ptr, with everything inlined,<b=
r>
it's actually not all *that* far-fetched that the compiler might be abl=
e<br>
to infer that the cting-dtor is trivial, even without being so marked,<br>
but that won't always be the case.)<br>
<br>
> I may have missed it above, but what is your reasoning for having the<=
br>
> implicit behavior perform move/copy+destruct rather than memberwise<br=
>
> destructive move? If it's safety, that could be handled by having =
the<br>
> implicit behavior predicated on the presence of a user-defined dtor or=
<br>
> copy/move ctor/assign, on the reasonable assumption that anything that=
is<br>
> location-aware (above its members) would have at least one of those sp=
ecial<br>
> functions user-defined.<br>
<br>
It is (for safety). If the ctor(s)/dtor are non-trivial, the implicit<br>
behavior should not be allowed to skip them. The "normative" beha=
vior<br>
therefore should be move/copy ctor + regular dtor.<br>
<br>
Note that I *did* say that the implicit behavior can be "trivial"=
, in<br>
which case despite the "normative" specification, the cting-dtor =
does in<br>
fact 'degenerate' into a memcpy.<br>
<br>
Basically, what that amounts to is there is *always* a cting-dtor unless<br=
>
it is deleted (implicitly or explicitly), with the implicit behavior<br>
always being The Right Thing=E2=84=A2, but also being efficient when it is<=
br>
provably correct to do so.<br>
<br>
I think where we're actually debating is on the implicit behavior being=
<br>
memberwise copy/move followed by memberwise destroy vs. memberwise<br>
cting-dtor. Those *should* be the same thing, unless there are<br>
order-dependent side effects. Even so, I can probably live with that;<br>
I'm just approaching the problem from something of an "as if"=
angle<br>
starting from the safest thing to do, while you're fully chasing down<b=
r>
possible optimizations.<br>
<span class=3D"HOEnZb"><font color=3D"#888888"><br>
--<br>
Matthew<br>
<br>
--<br>
<br>
---<br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/f1zaOjyUem0/unsubscribe" rel=3D"noreferr=
er" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/f1zaOjyUem0/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-proposals+unsubscrib=
e@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b6222e458598c051cbcd5af--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 07 Aug 2015 15:14:43 -0400
Raw View
On 2015-08-07 14:30, Edward Catmur wrote:
> If the ctor(s) and dtor are non-user-defined (defaulted or declared as
> defaulted) then the user has chosen to defer responsibility for copy/move
> operations to the bases and members, so why not let the bases and members
> decide? There's no user-written code being skipped.
Hmm... well, let's write it out. We're talking about e.g. this case:
class Foo { public: Foo(Foo&&); ~Foo(); };
struct Bar { Foo foo1; Foo foo2; }
So what does the implicit cting-dtor do here?
// option 1 (my suggestion)
Bar::~Bar(Bar* new_bar)
{
new (&new_bar->foo1) Foo{this->foo1};
new (&new_bar->foo2) Foo{this->foo2};
this->foo1.~Foo();
this->foo2.~Foo();
}
// option 2 (your suggestion)
Bar::~Bar(Bar* new_bar)
{
this->foo1->~Foo(&new_bar->foo1);
this->foo2->~Foo(&new_bar->foo2);
/* ...which often is equivalent to this:
new (&new_bar->foo1) Foo{this->foo1};
this->foo1.~Foo();
new (&new_bar->foo2) Foo{this->foo2};
this->foo2.~Foo();
*/
}
Well... okay; "often" may be the key word there. When it isn't, you *do*
end up paying more. OTOH, your way means a potential behavior change for
existing classes. (Yes, the whole feature is technically a behavior
change - except in the non-optimized cases - but in the trivial case,
there should be no *observable* change.)
Still... I am potentially convinced :-).
> Finally, requiring explicit opt-in is dangerous!
I still assert that if you *have* a user-defined copy/move ctor or dtor,
you must opt in to the cting-dtor doing other than copy/move plus
destroy of your class. Do we agree on that point?
Anyway, my intent was that one would not declare an explicitly
"defaulted" (or whatever ends up being used) cting-dtor unless the type
already has a non-default copy/move ctor and/or non-default regular
dtor. (And in that case, if you change the class without noticing the
cting-dtor, you are up a creek with either of our approaches :-).)
> If the implicit behavior is OTOH dependent on the presence/absence of
> the other special functions [...]
I never said it wasn't :-). Even with my previous suggestion, I said
that if the members' cting-dtors are all trivial, the aggregate's is
also trivial. The only case we disagreed on was when some member has a
non-trivial cting-dtor *but* the class has default copy/move ctor and
default regular dtor.
(So in either case, anything that e.g. looks like a C struct would
become trivially relocatable.)
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 10 Aug 2015 14:40:17 +0100
Raw View
--f46d0438959146d5cf051cf520d1
Content-Type: text/plain; charset=UTF-8
On Fri, Aug 7, 2015 at 8:14 PM, Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> I still assert that if you *have* a user-defined copy/move ctor or dtor,
> you must opt in to the cting-dtor doing other than copy/move plus
> destroy of your class. Do we agree on that point?
>
Absolutely.
> Anyway, my intent was that one would not declare an explicitly
> "defaulted" (or whatever ends up being used) cting-dtor unless the type
> already has a non-default copy/move ctor and/or non-default regular
> dtor. (And in that case, if you change the class without noticing the
> cting-dtor, you are up a creek with either of our approaches :-).)
>
> > If the implicit behavior is OTOH dependent on the presence/absence of
> > the other special functions [...]
>
> I never said it wasn't :-). Even with my previous suggestion, I said
> that if the members' cting-dtors are all trivial, the aggregate's is
> also trivial. The only case we disagreed on was when some member has a
> non-trivial cting-dtor *but* the class has default copy/move ctor and
> default regular dtor.
>
> (So in either case, anything that e.g. looks like a C struct would
> become trivially relocatable.)
>
Sounds great, thanks for working through this with me.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--f46d0438959146d5cf051cf520d1
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On F=
ri, Aug 7, 2015 at 8:14 PM, Matthew Woehlke <span dir=3D"ltr"><<a href=
=3D"mailto:mwoehlke.floss@gmail.com" target=3D"_blank">mwoehlke.floss@gmail=
..com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I still assert=
that if you *have* a user-defined copy/move ctor or dtor,<br>
you must opt in to the cting-dtor doing other than copy/move plus<br>
destroy of your class. Do we agree on that point?<br></blockquote><div><br>=
</div><div>Absolutely.</div><div>=C2=A0</div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"=
>
Anyway, my intent was that one would not declare an explicitly<br>
"defaulted" (or whatever ends up being used) cting-dtor unless th=
e type<br>
already has a non-default copy/move ctor and/or non-default regular<br>
dtor. (And in that case, if you change the class without noticing the<br>
cting-dtor, you are up a creek with either of our approaches :-).)<br>
<br>
> If the implicit behavior is OTOH dependent on the presence/absence of<=
br>
> the other special functions [...]<br>
<br>
I never said it wasn't :-). Even with my previous suggestion, I said<br=
>
that if the members' cting-dtors are all trivial, the aggregate's i=
s<br>
also trivial. The only case we disagreed on was when some member has a<br>
non-trivial cting-dtor *but* the class has default copy/move ctor and<br>
default regular dtor.<br>
<br>
(So in either case, anything that e.g. looks like a C struct would<br>
become trivially relocatable.)<br></blockquote><div><br></div><div>Sounds g=
reat, thanks for working through this with me.=C2=A0</div></div></div></div=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--f46d0438959146d5cf051cf520d1--
.