Topic: Better Performance in Polymorphic
Author: =?UTF-8?B?R2HFoXBlciBBxb5tYW4=?= <gasper.azman@gmail.com>
Date: Fri, 29 Jun 2018 09:55:44 +0100
Raw View
--0000000000003ceda3056fc404ba
Content-Type: text/plain; charset="UTF-8"
How does this interface with the concept of relocatable? One would think
relocatable implies trivially swappable, same as noexcept movable implies
noexcept swappable.
G
On Fri, Jun 29, 2018, 08:19 Mingxin Wang <wmx16835vv@163.com> wrote:
>
> On Friday, June 29, 2018 at 12:16:05 PM UTC+8, Nicol Bolas wrote:
>>
>> On Thursday, June 28, 2018 at 11:45:08 PM UTC-4, Mingxin Wang wrote:
>>>
>>> During the process of implementing the proposal P0957 (
>>> https://wg21.link/p0957), I found that if the concept of "Trivially
>>> Swappable" is defined, the performance of the implementation of will be
>>> improved to a certain extent without reducing usability.
>>>
>>
>> OK, so... what would this concept mean? Can you provide a definition of
>> these requirements and what they would allow you to do?
>>
>
> Informally, a type meets the *TriviallySwappable* requirements if the
> "std::swap" function overload of this type performs bitwise swap operation.
>
>
>>
>> I am also wondering if this concept could help in generating default move
>>> constructors.
>>>
>>
>> Do we need help generating default move constructors? Is `= default` not
>> good enough? Or are you talking about something else?
>>
>
> If the construction of a type involves heap allocation with exclusive
> ownership, e.g. `std::unique_ptr`, the default move constructor will not
> work. But as long as `std::unique_ptr` is TriviallySwappable and
> DefaultConstructible, the move constructor could be generated with the
> default constructor and bitwise swap, which is equivalent to the semantics
> defined in the standard.
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/18469feb-bdda-466d-ba8c-37933c1ea807%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/18469feb-bdda-466d-ba8c-37933c1ea807%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAANG%3DkU-fFnRMx9O2JGWHGvEaGSAbkDS0cK%2Bw1-5F54fC6Evgg%40mail.gmail.com.
--0000000000003ceda3056fc404ba
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto">How does this interface with the concept of relocatable? =
One would think relocatable implies trivially swappable, same as noexcept m=
ovable implies noexcept swappable.<div dir=3D"auto"><br></div><div dir=3D"a=
uto">G</div></div><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Fri, J=
un 29, 2018, 08:19 Mingxin Wang <<a href=3D"mailto:wmx16835vv@163.com">w=
mx16835vv@163.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><br>On Friday, June 29, 2018 at 12:16:05 PM UTC+8, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Thursd=
ay, June 28, 2018 at 11:45:08 PM UTC-4, Mingxin Wang wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div>During the process of impleme=
nting the proposal P0957 (<a href=3D"https://wg21.link/p0957" rel=3D"nofoll=
ow noreferrer" target=3D"_blank">https://wg21.link/p0957</a>), I found that=
if the concept of "Trivially Swappable" is defined, the performa=
nce of the implementation of will be improved to a certain extent without r=
educing usability.</div></div></blockquote><div><br></div><div>OK, so... wh=
at would this concept mean? Can you provide a definition of these requireme=
nts and what they would allow you to do?</div></div></blockquote><div><br><=
/div><div>Informally, a type meets the <b>TriviallySwappable</b> requiremen=
ts if the "std::swap" function overload of this type performs bit=
wise swap operation.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div></div><div>I am also wondering if this concept c=
ould help in generating default move constructors.</div></div></blockquote>=
<div><br></div><div>Do we need help generating default move constructors? I=
s `=3D default` not good enough? Or are you talking about something else?</=
div></div></blockquote><div><br></div><div>If the construction of a type in=
volves heap allocation with exclusive ownership, e.g. `std::unique_ptr`, th=
e default move constructor will not work. But as long as `std::unique_ptr` =
is TriviallySwappable and DefaultConstructible, the move constructor could =
be generated with the default constructor and bitwise swap, which is=C2=A0e=
quivalent to the semantics defined in the standard.</div></div>
<p></p>
-- <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" target=3D"_=
blank" rel=3D"noreferrer">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" rel=3D"noreferrer">std-proposals@isocpp.org</a>.<br=
>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/18469feb-bdda-466d-ba8c-37933c1ea807%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/msgid/std-propo=
sals/18469feb-bdda-466d-ba8c-37933c1ea807%40isocpp.org</a>.<br>
</blockquote></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAANG%3DkU-fFnRMx9O2JGWHGvEaGSAbkDS0c=
K%2Bw1-5F54fC6Evgg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAANG%3DkU-fF=
nRMx9O2JGWHGvEaGSAbkDS0cK%2Bw1-5F54fC6Evgg%40mail.gmail.com</a>.<br />
--0000000000003ceda3056fc404ba--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 29 Jun 2018 15:08:01 -0700
Raw View
On Friday, 29 June 2018 00:19:40 PDT Mingxin Wang wrote:
> Informally, a type meets the *TriviallySwappable* requirements if the
> "std::swap" function overload of this type performs bitwise swap operation.
Why do you need the concept? Why can't you just use std::swap for your use-
case?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2504483.4B7iPY4hye%40tjmaciei-mobl1.
.
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Fri, 29 Jun 2018 15:51:11 -0700 (PDT)
Raw View
------=_Part_16707_1967254022.1530312672029
Content-Type: multipart/alternative;
boundary="----=_Part_16708_1702635765.1530312672029"
------=_Part_16708_1702635765.1530312672029
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman wrote:
>
> How does this interface with the concept of relocatable? One would think=
=20
> relocatable implies trivially swappable, same as noexcept movable implies=
=20
> noexcept swappable.
>
In my C++Now 2018 talk on "trivially relocatable,"=20
<https://www.youtube.com/watch?v=3DMWBfmmg8-Yo> I promised in the outline t=
o=20
talk about its relationship to "trivially swappable," and then did not=20
actually do so =E2=80=94 sorry!
Essentially, yes, if a type is trivially relocatable then it intuitively=20
ought to be considered trivially swappable. However, there are two minor=
=20
caveats that I can think of off the top of my head (and the reason I didn't=
=20
talk about it at C++Now is that I haven't thought about it much, and the=20
reason for *that* is that I don't have a motivating use-case).
Caveat (A): Trivial relocation can be optimized into memcpy() or memmove().=
=20
Trivial swap cannot be optimized into mem-anything, because there is no=20
libc primitive for *swapping* arrays of bytes. We could certainly propose=
=20
to add a __builtin_memswap() that would perform the swap "in-place" in=20
cache-line-sized blocks, but I'm not aware of any proposals nor prior art=
=20
in that area.
Caveat (B): Notice that whereas "relocate" means "move-construct, then=20
destroy", we might say that "swap" means "move-construct, then move-assign,=
=20
then move-assign, then destroy." (This being the operation done by the=20
unconstrained std::swap template.) This involves a relationship among 3=20
operations, which might be a little scarier than relocate's relationship=20
among 2 operations, which is scarier than the current Standard Library's=20
"trivially X" traits which all involve only a single operation.
Caveat (C): For small types like unique_ptr, __builtin_memswap() will not=
=20
be any faster than the unconstrained std::swap template. The point of=20
optimizing into mem-anything is to get speedups on *large* arrays, such as=
=20
during std::vector reallocation. std::vector swapping is already fast, and=
=20
cannot be made faster by __builtin_memswap(). Now, std::array swapping=20
could be made faster; consider=E2=80=94
std::array<std::unique_ptr<int>, 10000> a;
std::array<std::unique_ptr<int>, 10000> b;
a.swap(b); // could probably get a factor-of-2 speedup on this=20
operation by using __builtin_memswap
But, this is not an operation that happens often enough in real programs=20
for anyone to get really motivated about.
TLDR I think "trivially swappable" is a straightforward corollary to=20
"trivially relocatable", but its cost-of-specification might be a bit=20
higher, and its benefit-in-performance is essentially zero as far as any=20
use-case *I* can think of.
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/c9b311f5-c80e-4dac-9d1e-55751ecd747f%40isocpp.or=
g.
------=_Part_16708_1702635765.1530312672029
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per =
A=C5=BEman wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"a=
uto">How does this interface with the concept of relocatable? One would thi=
nk relocatable implies trivially swappable, same as noexcept movable implie=
s noexcept swappable.</div></blockquote><div><br></div><div>In <a href=3D"h=
ttps://www.youtube.com/watch?v=3DMWBfmmg8-Yo">my C++Now 2018 talk on "=
trivially relocatable,"</a> I promised in the outline to talk about it=
s relationship to "trivially swappable," and then did not actuall=
y do so =E2=80=94 sorry!</div><div>Essentially, yes, if a type is trivially=
relocatable then it intuitively ought to be considered trivially swappable=
.. =C2=A0However, there are two minor caveats that I can think of off the to=
p of my head (and the reason I didn't talk about it at C++Now is that I=
haven't thought about it much, and the reason for *that* is that I don=
't have a motivating use-case).</div><div><br></div><div>Caveat (A): Tr=
ivial relocation can be optimized into memcpy() or memmove(). =C2=A0Trivial=
swap cannot be optimized into mem-anything, because there is no libc primi=
tive for <i>swapping</i> arrays of bytes. We could certainly propose to add=
a __builtin_memswap() that would perform the swap "in-place" in =
cache-line-sized blocks, but I'm not aware of any proposals nor prior a=
rt in that area.</div><div><br></div><div>Caveat (B): Notice that whereas &=
quot;relocate" means "move-construct, then destroy", we migh=
t say that "swap" means "move-construct, then move-assign, t=
hen move-assign, then destroy." (This being the operation done by the =
unconstrained std::swap template.) =C2=A0This involves a relationship among=
3 operations, which might be a little scarier than relocate's relation=
ship among 2 operations, which is scarier than the current Standard Library=
's "trivially X" traits which all involve only a single opera=
tion.</div><div><br></div><div>Caveat (C): For small types like unique_ptr,=
__builtin_memswap() will not be any faster than the unconstrained std::swa=
p template. The point of optimizing into mem-anything is to get speedups on=
<i>large</i> arrays, such as during std::vector reallocation. =C2=A0std::v=
ector swapping is already fast, and cannot be made faster by __builtin_mems=
wap(). =C2=A0Now, std::array swapping could be made faster; consider=E2=80=
=94</div><div><br></div><div>=C2=A0 =C2=A0 std::array<std::unique_ptr<=
;int>, 10000> a;</div><div><div>=C2=A0 =C2=A0 std::array<std::uniq=
ue_ptr<int>, 10000> b;</div></div><div>=C2=A0 =C2=A0 a.swap(b); =
=C2=A0// could probably get a factor-of-2 speedup on this operation by usin=
g __builtin_memswap</div><div><br></div><div>But, this is not an operation =
that happens often enough in real programs for anyone to get really motivat=
ed about.</div><div><br></div><div>TLDR I think "trivially swappable&q=
uot; is a straightforward corollary to "trivially relocatable", b=
ut its cost-of-specification might be a bit higher, and its benefit-in-perf=
ormance is essentially zero as far as any use-case <i>I</i> can think of.</=
div><div><br></div><div>=E2=80=93Arthur</div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/c9b311f5-c80e-4dac-9d1e-55751ecd747f%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c9b311f5-c80e-4dac-9d1e-55751ecd747f=
%40isocpp.org</a>.<br />
------=_Part_16708_1702635765.1530312672029--
------=_Part_16707_1967254022.1530312672029--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 29 Jun 2018 17:58:42 -0700 (PDT)
Raw View
------=_Part_17417_1766977370.1530320322567
Content-Type: multipart/alternative;
boundary="----=_Part_17418_598564135.1530320322568"
------=_Part_17418_598564135.1530320322568
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, June 29, 2018 at 6:51:12 PM UTC-4, Arthur O'Dwyer wrote:
>
> On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman wrot=
e:
>>
>> How does this interface with the concept of relocatable? One would think=
=20
>> relocatable implies trivially swappable, same as noexcept movable implie=
s=20
>> noexcept swappable.
>>
>
> In my C++Now 2018 talk on "trivially relocatable,"=20
> <https://www.youtube.com/watch?v=3DMWBfmmg8-Yo> I promised in the outline=
=20
> to talk about its relationship to "trivially swappable," and then did not=
=20
> actually do so =E2=80=94 sorry!
> Essentially, yes, if a type is trivially relocatable then it intuitively=
=20
> ought to be considered trivially swappable. However, there are two minor=
=20
> caveats that I can think of off the top of my head (and the reason I didn=
't=20
> talk about it at C++Now is that I haven't thought about it much, and the=
=20
> reason for *that* is that I don't have a motivating use-case).
>
> Caveat (A): Trivial relocation can be optimized into memcpy() or=20
> memmove(). Trivial swap cannot be optimized into mem-anything, because=
=20
> there is no libc primitive for *swapping* arrays of bytes. We could=20
> certainly propose to add a __builtin_memswap() that would perform the swa=
p=20
> "in-place" in cache-line-sized blocks, but I'm not aware of any proposals=
=20
> nor prior art in that area.
>
Performing a byte copy on a TrivialRelocatable object into another object=
=20
of that type leaves the original object in a conceptually invalid state.=20
That is, even though it is technically valid, if you called its destructor,=
=20
that would be really bad. You will have violated the TrivialRelocatable=20
agreement.
However, if you take an object which is invalid through TrivialRelocation,=
=20
and perform a trivial relocation operation into that, then the object=20
should be considered valid again.
A trivial swap operation is merely this:
void trivial_swap(T &a, T &b)
{
std::byte buff[sizeof(T)];
memcpy(buff, &a, sizeof(T));
memcpy(&a, &b, sizeof(T)); //b is no longer valid.
memcpy(&b, buff, sizeof(T)); //b is valid again.
}
I believe the validity of this code naturally falls out of a type being=20
TriviallyRelocatable.
`b` stopped being valid because we copied its values into a living object=
=20
of type `T`, and thus that object took ownership over those values. But=20
`buff` contains values of a now orphaned object. By copying that value into=
=20
`b`, we unorphan that object's values.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/5667a508-2c18-474f-a66a-be18f05df835%40isocpp.or=
g.
------=_Part_17418_598564135.1530320322568
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 29, 2018 at 6:51:12 PM UTC-4, Arthur O'=
;Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"auto">How does this int=
erface with the concept of relocatable? One would think relocatable implies=
trivially swappable, same as noexcept movable implies noexcept swappable.<=
/div></blockquote><div><br></div><div>In <a href=3D"https://www.youtube.com=
/watch?v=3DMWBfmmg8-Yo" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"t=
his.href=3D'https://www.youtube.com/watch?v\x3dMWBfmmg8-Yo';return =
true;" onclick=3D"this.href=3D'https://www.youtube.com/watch?v\x3dMWBfm=
mg8-Yo';return true;">my C++Now 2018 talk on "trivially relocatabl=
e,"</a> I promised in the outline to talk about its relationship to &q=
uot;trivially swappable," and then did not actually do so =E2=80=94 so=
rry!</div><div>Essentially, yes, if a type is trivially relocatable then it=
intuitively ought to be considered trivially swappable. =C2=A0However, the=
re are two minor caveats that I can think of off the top of my head (and th=
e reason I didn't talk about it at C++Now is that I haven't thought=
about it much, and the reason for *that* is that I don't have a motiva=
ting use-case).</div><div><br></div><div>Caveat (A): Trivial relocation can=
be optimized into memcpy() or memmove(). =C2=A0Trivial swap cannot be opti=
mized into mem-anything, because there is no libc primitive for <i>swapping=
</i> arrays of bytes. We could certainly propose to add a __builtin_memswap=
() that would perform the swap "in-place" in cache-line-sized blo=
cks, but I'm not aware of any proposals nor prior art in that area.</di=
v></div></blockquote><div><br></div><div></div><div>Performing a byte copy =
on a TrivialRelocatable object into another object of that type leaves the =
original object in a conceptually invalid state. That is, even though it is=
technically valid, if you called its destructor, that would be really bad.=
You will have violated the TrivialRelocatable agreement.</div><div><br></d=
iv><div>However, if you take an object which is invalid through TrivialRelo=
cation, and perform a trivial relocation operation into that, then the obje=
ct should be considered valid again.<br></div><div><br></div><div>A trivial=
swap operation is merely this:</div><div><br></div><div style=3D"backgroun=
d-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style=
: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprin=
t"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D=
"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> trivial_swap</span><span style=3D"co=
lor: #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"s=
tyled-by-prettify">a</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">b</span><sp=
an 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"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">byte</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> buff</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">[</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">)];</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 memcpy</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">buff</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">a</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">si=
zeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">));</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 memcpy</span><span s=
tyle=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-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">b</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span=
><span 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: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">//b is no longer valid.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 memcpy</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 style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> buff</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=
">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">));</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #800;" class=3D"styled-by-prettify">//b is valid again.</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span></div></code></div><div><=
br></div><div>I believe the validity of this code naturally falls out of a =
type being TriviallyRelocatable.</div><div><br></div><div>`b` stopped being=
valid because we copied its values into a living object of type `T`, and t=
hus that object took ownership over those values. But `buff` contains value=
s of a now orphaned object. By copying that value into `b`, we unorphan tha=
t object's values.<br></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5667a508-2c18-474f-a66a-be18f05df835%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5667a508-2c18-474f-a66a-be18f05df835=
%40isocpp.org</a>.<br />
------=_Part_17418_598564135.1530320322568--
------=_Part_17417_1766977370.1530320322567--
.
Author: Mingxin Wang <wmx16835vv@163.com>
Date: Fri, 29 Jun 2018 18:03:26 -0700 (PDT)
Raw View
------=_Part_17844_1665425138.1530320606154
Content-Type: multipart/alternative;
boundary="----=_Part_17845_281940666.1530320606154"
------=_Part_17845_281940666.1530320606154
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Saturday, June 30, 2018 at 6:51:12 AM UTC+8, Arthur O'Dwyer wrote:
>
> Caveat (A): Trivial relocation can be optimized into memcpy() or=20
> memmove(). Trivial swap cannot be optimized into mem-anything, because=
=20
> there is no libc primitive for *swapping* arrays of bytes. We could=20
> certainly propose to add a __builtin_memswap() that would perform the swa=
p=20
> "in-place" in cache-line-sized blocks, but I'm not aware of any proposals=
=20
> nor prior art in that area.
>
I think it is acceptible just to make it "implementation-defined". If the=
=20
type to swap is small, the compiler may generate specific instructions=20
performing efficient copy operations for 1, 2, 4, 8... bytes (or tricks=20
like `a ^=3D b ^=3D a ^=3D b`). Otherswise, the implementation may invoke=
=20
`memcpy` twice. This is the usual implementation I have seen for the=20
specializations of `std::swap`.
Caveat (B): Notice that whereas "relocate" means "move-construct, then=20
> destroy", we might say that "swap" means "move-construct, then move-assig=
n,=20
> then move-assign, then destroy." (This being the operation done by the=20
> unconstrained std::swap template.) This involves a relationship among 3=
=20
> operations, which might be a little scarier than relocate's relationship=
=20
> among 2 operations, which is scarier than the current Standard Library's=
=20
> "trivially X" traits which all involve only a single operation.
>
By saying "I am also wondering if this concept could help in generating=20
default move constructors", I am thinking of the possibility to make "swap"=
=20
a primitive, in other words, to make "swap beneath move", and the generated=
=20
move constructors are always exception-safe.
Caveat (C): For small types like unique_ptr, __builtin_memswap() will not=
=20
> be any faster than the unconstrained std::swap template. The point of=20
> optimizing into mem-anything is to get speedups on *large* arrays, such=
=20
> as during std::vector reallocation. std::vector swapping is already fast=
,=20
> and cannot be made faster by __builtin_memswap(). Now, std::array swappi=
ng=20
> could be made faster; consider=E2=80=94
>
> std::array<std::unique_ptr<int>, 10000> a;
> std::array<std::unique_ptr<int>, 10000> b;
> a.swap(b); // could probably get a factor-of-2 speedup on this=20
> operation by using __builtin_memswap
>
> But, this is not an operation that happens often enough in real programs=
=20
> for anyone to get really motivated about.
>
The main motivation for the TriviallySwappable requirements is to avoid=20
unnecessary runtime dispatch in polymorphic use cases, and it has been=20
briefly illustrated in my initial post.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/9fb2cf54-a69b-47ea-99c4-5a43f5d5a638%40isocpp.or=
g.
------=_Part_17845_281940666.1530320606154
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 30, 2018 at 6:51:12 AM UTC+8, Arthur O&#=
39;Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div>Caveat (A): Trivial relocation can be optimized into memcpy() or mem=
move(). =C2=A0Trivial swap cannot be optimized into mem-anything, because t=
here is no libc primitive for <i>swapping</i> arrays of bytes. We could cer=
tainly propose to add a __builtin_memswap() that would perform the swap &qu=
ot;in-place" in cache-line-sized blocks, but I'm not aware of any =
proposals nor prior art in that area.</div></div></blockquote><div><br></di=
v><div>I think it is acceptible just to make it "implementation-define=
d". If the type to swap is small, the compiler may generate specific i=
nstructions performing efficient copy operations for 1, 2, 4, 8... bytes (o=
r tricks like `a ^=3D b ^=3D a ^=3D b`). Otherswise, the implementation may=
invoke `memcpy` twice. This is the usual implementation I have seen for th=
e specializations of `std::swap`.</div><div><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div>Caveat (B): Notice that where=
as "relocate" means "move-construct, then destroy", we =
might say that "swap" means "move-construct, then move-assig=
n, then move-assign, then destroy." (This being the operation done by =
the unconstrained std::swap template.) =C2=A0This involves a relationship a=
mong 3 operations, which might be a little scarier than relocate's rela=
tionship among 2 operations, which is scarier than the current Standard Lib=
rary's "trivially X" traits which all involve only a single o=
peration.</div></div></blockquote><div><br></div><div>By saying "I am =
also wondering if this concept could help in generating default move constr=
uctors", I am thinking of the possibility to make "swap" a p=
rimitive, in other words, to make "swap beneath move", and the ge=
nerated move constructors are always=C2=A0exception-safe.<br></div><div><br=
></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>C=
aveat (C): For small types like unique_ptr, __builtin_memswap() will not be=
any faster than the unconstrained std::swap template. The point of optimiz=
ing into mem-anything is to get speedups on <i>large</i> arrays, such as du=
ring std::vector reallocation. =C2=A0std::vector swapping is already fast, =
and cannot be made faster by __builtin_memswap(). =C2=A0Now, std::array swa=
pping could be made faster; consider=E2=80=94</div><div><br></div><div>=C2=
=A0 =C2=A0 std::array<std::unique_ptr<<wbr>int>, 10000> a;</div=
><div><div>=C2=A0 =C2=A0 std::array<std::unique_ptr<<wbr>int>, 100=
00> b;</div></div><div>=C2=A0 =C2=A0 a.swap(b); =C2=A0// could probably =
get a factor-of-2 speedup on this operation by using __builtin_memswap</div=
><div><br></div><div>But, this is not an operation that happens often enoug=
h in real programs for anyone to get really motivated about.</div></div></b=
lockquote><div><br></div><div>The main motivation for the TriviallySwappabl=
e requirements is to avoid unnecessary runtime dispatch in polymorphic use =
cases, and it has been briefly illustrated in my initial post.</div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9fb2cf54-a69b-47ea-99c4-5a43f5d5a638%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9fb2cf54-a69b-47ea-99c4-5a43f5d5a638=
%40isocpp.org</a>.<br />
------=_Part_17845_281940666.1530320606154--
------=_Part_17844_1665425138.1530320606154--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 29 Jun 2018 18:04:50 -0700 (PDT)
Raw View
------=_Part_17617_1979817334.1530320690063
Content-Type: multipart/alternative;
boundary="----=_Part_17618_791852443.1530320690063"
------=_Part_17618_791852443.1530320690063
Content-Type: text/plain; charset="UTF-8"
On Friday, June 29, 2018 at 6:08:10 PM UTC-4, Thiago Macieira wrote:
>
> On Friday, 29 June 2018 00:19:40 PDT Mingxin Wang wrote:
> > Informally, a type meets the *TriviallySwappable* requirements if the
> > "std::swap" function overload of this type performs bitwise swap
> operation.
>
> Why do you need the concept? Why can't you just use std::swap for your
> use-
> case?
>
He didn't really explain the problem very well. It's a performance issue,
not a functionality issue.
Say you have a type-erased type like `any`. It's storing some type-erased
value, and it's using small buffer optimization. If you move an `any`, and
the stored object fits within the small buffer (like a `unique_ptr<T>`),
then you can only move it by invoking `unique_ptr<T>`'s move constructor.
This requires an indirect call through the type-erasure machinery.
That's slow.
A swap operation would require 3 of these moves. That's really slow.
However, if the `any` could, at swap time, detect that its contents were
TriviallySwappable, it could perform the swap with 3 memcpy operations.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5851a3b1-714a-4563-bfb6-4659730bca87%40isocpp.org.
------=_Part_17618_791852443.1530320690063
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 29, 2018 at 6:08:10 PM UTC-4, Thiago Macie=
ira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Friday, 29 June 2=
018 00:19:40 PDT Mingxin Wang wrote:
<br>> Informally, a type meets the *TriviallySwappable* requirements if =
the
<br>> "std::swap" function overload of this type performs bitw=
ise swap operation.
<br>
<br>Why do you need the concept? Why can't you just use std::swap for y=
our use-
<br>case?
<br></blockquote><div><br></div><div>He didn't really explain the probl=
em very well. It's a performance issue, not a functionality issue.</div=
><div><br></div><div>Say you have a type-erased type like `any`. It's s=
toring some type-erased value, and it's using small buffer optimization=
.. If you move an `any`, and the stored object fits within the small buffer =
(like a `unique_ptr<T>`), then you can only move it by invoking `uniq=
ue_ptr<T>`'s move constructor. This requires an indirect call thr=
ough the type-erasure machinery.</div><div><br></div><div>That's slow.<=
/div><div><br></div><div>A swap operation would require 3 of these moves. T=
hat's really slow.<br></div><div><br></div><div>However, if the `any` c=
ould, at swap time, detect that its contents were TriviallySwappable, it co=
uld perform the swap with 3 memcpy operations.<br></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5851a3b1-714a-4563-bfb6-4659730bca87%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5851a3b1-714a-4563-bfb6-4659730bca87=
%40isocpp.org</a>.<br />
------=_Part_17618_791852443.1530320690063--
------=_Part_17617_1979817334.1530320690063--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 29 Jun 2018 18:09:21 -0700 (PDT)
Raw View
------=_Part_17277_197242660.1530320961340
Content-Type: multipart/alternative;
boundary="----=_Part_17278_890997859.1530320961341"
------=_Part_17278_890997859.1530320961341
Content-Type: text/plain; charset="UTF-8"
On Friday, June 29, 2018 at 9:03:26 PM UTC-4, Mingxin Wang wrote:
>
> On Saturday, June 30, 2018 at 6:51:12 AM UTC+8, Arthur O'Dwyer wrote:
>>
>> Caveat (A): Trivial relocation can be optimized into memcpy() or
>> memmove(). Trivial swap cannot be optimized into mem-anything, because
>> there is no libc primitive for *swapping* arrays of bytes. We could
>> certainly propose to add a __builtin_memswap() that would perform the swap
>> "in-place" in cache-line-sized blocks, but I'm not aware of any proposals
>> nor prior art in that area.
>>
>
> I think it is acceptible just to make it "implementation-defined". If the
> type to swap is small, the compiler may generate specific instructions
> performing efficient copy operations for 1, 2, 4, 8... bytes (or tricks
> like `a ^= b ^= a ^= b`). Otherswise, the implementation may invoke
> `memcpy` twice. This is the usual implementation I have seen for the
> specializations of `std::swap`.
>
> Caveat (B): Notice that whereas "relocate" means "move-construct, then
>> destroy", we might say that "swap" means "move-construct, then move-assign,
>> then move-assign, then destroy." (This being the operation done by the
>> unconstrained std::swap template.) This involves a relationship among 3
>> operations, which might be a little scarier than relocate's relationship
>> among 2 operations, which is scarier than the current Standard Library's
>> "trivially X" traits which all involve only a single operation.
>>
>
> By saying "I am also wondering if this concept could help in generating
> default move constructors", I am thinking of the possibility to make "swap"
> a primitive, in other words, to make "swap beneath move", and the generated
> move constructors are always exception-safe.
>
That would not have that effect. A type with a throwing move constructor is
one that cannot be empty, and therefore allocates state even if it is
empty. The classic example being `std::list` implementations that are
required to have a single node. Your "swap primitive" wouldn't be able to
allocate that memory, so it could not use that implementation.
Compiler-generated move constructors are always as exception-safe as the
move constructors they call. And your feature here can't change that.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2dd77149-bdba-43c8-8eb3-86c3dce69b7e%40isocpp.org.
------=_Part_17278_890997859.1530320961341
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 29, 2018 at 9:03:26 PM UTC-4, Mingxin Wang=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Sat=
urday, June 30, 2018 at 6:51:12 AM UTC+8, Arthur O'Dwyer wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Caveat (A): Trivial r=
elocation can be optimized into memcpy() or memmove(). =C2=A0Trivial swap c=
annot be optimized into mem-anything, because there is no libc primitive fo=
r <i>swapping</i> arrays of bytes. We could certainly propose to add a __bu=
iltin_memswap() that would perform the swap "in-place" in cache-l=
ine-sized blocks, but I'm not aware of any proposals nor prior art in t=
hat area.</div></div></blockquote><div><br></div><div>I think it is accepti=
ble just to make it "implementation-defined". If the type to swap=
is small, the compiler may generate specific instructions performing effic=
ient copy operations for 1, 2, 4, 8... bytes (or tricks like `a ^=3D b ^=3D=
a ^=3D b`). Otherswise, the implementation may invoke `memcpy` twice. This=
is the usual implementation I have seen for the specializations of `std::s=
wap`.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Caveat (B): Notice that whereas "relocate" means &q=
uot;move-construct, then destroy", we might say that "swap" =
means "move-construct, then move-assign, then move-assign, then destro=
y." (This being the operation done by the unconstrained std::swap temp=
late.) =C2=A0This involves a relationship among 3 operations, which might b=
e a little scarier than relocate's relationship among 2 operations, whi=
ch is scarier than the current Standard Library's "trivially X&quo=
t; traits which all involve only a single operation.</div></div></blockquot=
e><div><br></div><div>By saying "I am also wondering if this concept c=
ould help in generating default move constructors", I am thinking of t=
he possibility to make "swap" a primitive, in other words, to mak=
e "swap beneath move", and the generated move constructors are al=
ways=C2=A0exception-safe.<br></div></div></blockquote><div><br></div><div>T=
hat would not have that effect. A type with a throwing move constructor is =
one that cannot be empty, and therefore allocates state even if it is empty=
.. The classic example being `std::list` implementations that are required t=
o have a single node. Your "swap primitive" wouldn't be able =
to allocate that memory, so it could not use that implementation.</div><div=
><br></div><div>Compiler-generated move constructors are always as exceptio=
n-safe as the move constructors they call. And your feature here can't =
change that.<br></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/2dd77149-bdba-43c8-8eb3-86c3dce69b7e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2dd77149-bdba-43c8-8eb3-86c3dce69b7e=
%40isocpp.org</a>.<br />
------=_Part_17278_890997859.1530320961341--
------=_Part_17277_197242660.1530320961340--
.
Author: Mingxin Wang <wmx16835vv@163.com>
Date: Fri, 29 Jun 2018 19:10:33 -0700 (PDT)
Raw View
------=_Part_8569_1911667568.1530324633485
Content-Type: multipart/alternative;
boundary="----=_Part_8570_781865745.1530324633486"
------=_Part_8570_781865745.1530324633486
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 30, 2018 at 9:09:21 AM UTC+8, Nicol Bolas wrote:
>
> On Friday, June 29, 2018 at 9:03:26 PM UTC-4, Mingxin Wang wrote:
>>
>> By saying "I am also wondering if this concept could help in generating
>> default move constructors", I am thinking of the possibility to make "swap"
>> a primitive, in other words, to make "swap beneath move", and the generated
>> move constructors are always exception-safe.
>>
>
> That would not have that effect. A type with a throwing move constructor
> is one that cannot be empty, and therefore allocates state even if it is
> empty. The classic example being `std::list` implementations that are
> required to have a single node. Your "swap primitive" wouldn't be able to
> allocate that memory, so it could not use that implementation.
>
I do not see the difference between allocating constructions and
non-allocating constructions. Generating move constructors with `swap`
requires the types to be trivially swappable and default constructible,
rather than trivially default constructible. Thus I think the move
constructor of `std::list` can theoretically be generated with `swap`.
Compiler-generated move constructors are always as exception-safe as the
> move constructors they call. And your feature here can't change that.
>
You are right about that. However, the default constructors are not always
correct, e.g. for `std::unique_ptr`, because there is a chance for the
default move constructors to have different semantics from other
hand-written constructors. Generating move constructors with `swap` could
avoid such abuse.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c08d0ac8-4d1d-452f-aea1-fc32bb49ba4d%40isocpp.org.
------=_Part_8570_781865745.1530324633486
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 30, 2018 at 9:09:21 AM UTC+8, Nicol Bola=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Fr=
iday, June 29, 2018 at 9:03:26 PM UTC-4, Mingxin Wang wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div>By saying "I am also wo=
ndering if this concept could help in generating default move constructors&=
quot;, I am thinking of the possibility to make "swap" a primitiv=
e, in other words, to make "swap beneath move", and the generated=
move constructors are always=C2=A0exception-safe.<br></div></div></blockqu=
ote><div><br></div><div>That would not have that effect. A type with a thro=
wing move constructor is one that cannot be empty, and therefore allocates =
state even if it is empty. The classic example being `std::list` implementa=
tions that are required to have a single node. Your "swap primitive&qu=
ot; wouldn't be able to allocate that memory, so it could not use that =
implementation.</div></div></blockquote><div><br></div><div>I do not see th=
e difference between allocating constructions and non-allocating constructi=
ons. Generating move constructors with `swap` requires the types to be triv=
ially swappable and default constructible, rather than trivially default co=
nstructible. Thus I think the move constructor of `std::list`=C2=A0can theo=
retically be generated with `swap`.</div><div><br></div><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"><div>Compiler-generated move c=
onstructors are always as exception-safe as the move constructors they call=
.. And your feature here can't change that.<br></div></div></blockquote>=
<div><br></div><div>You are right about that. However, the default construc=
tors are not always correct, e.g. for `std::unique_ptr`, because there is a=
chance for the default move constructors to have different semantics from =
other hand-written constructors. Generating move constructors with `swap` c=
ould avoid such abuse.</div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/c08d0ac8-4d1d-452f-aea1-fc32bb49ba4d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c08d0ac8-4d1d-452f-aea1-fc32bb49ba4d=
%40isocpp.org</a>.<br />
------=_Part_8570_781865745.1530324633486--
------=_Part_8569_1911667568.1530324633485--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 29 Jun 2018 20:23:29 -0700 (PDT)
Raw View
------=_Part_18119_508097506.1530329009827
Content-Type: multipart/alternative;
boundary="----=_Part_18120_1775271743.1530329009827"
------=_Part_18120_1775271743.1530329009827
Content-Type: text/plain; charset="UTF-8"
On Friday, June 29, 2018 at 10:10:33 PM UTC-4, Mingxin Wang wrote:
>
> On Saturday, June 30, 2018 at 9:09:21 AM UTC+8, Nicol Bolas wrote:
>>
>> On Friday, June 29, 2018 at 9:03:26 PM UTC-4, Mingxin Wang wrote:
>>>
>>> By saying "I am also wondering if this concept could help in generating
>>> default move constructors", I am thinking of the possibility to make "swap"
>>> a primitive, in other words, to make "swap beneath move", and the generated
>>> move constructors are always exception-safe.
>>>
>>
>> That would not have that effect. A type with a throwing move constructor
>> is one that cannot be empty, and therefore allocates state even if it is
>> empty. The classic example being `std::list` implementations that are
>> required to have a single node. Your "swap primitive" wouldn't be able to
>> allocate that memory, so it could not use that implementation.
>>
>
> I do not see the difference between allocating constructions and
> non-allocating constructions. Generating move constructors with `swap`
> requires the types to be trivially swappable and default constructible,
> rather than trivially default constructible. Thus I think the move
> constructor of `std::list` can theoretically be generated with `swap`.
>
It could, but it still wouldn't be noexcept because `std::list`'s default
constructor is not noexcept. Or more specifically, it is not required to be.
So you've gained nothing.
Also, trivial swapping should not require default constructible. The whole
point of trivial-anyability is that it can be done via memcpy of bytes. So
a trivial swap should be able to work through a byte array.
Compiler-generated move constructors are always as exception-safe as the
>> move constructors they call. And your feature here can't change that.
>>
>
> You are right about that. However, the default constructors are not always
> correct, e.g. for `std::unique_ptr`, because there is a chance for the
> default move constructors to have different semantics from other
> hand-written constructors. Generating move constructors with `swap` could
> avoid such abuse.
>
The ability of hand-written constructors to have different behavior from
default constructors is not "abuse". It's why you can write move
constructors at all.
Default move constructors should not try to be fancy. They should provide
very simple, very obvious semantics: move each element. The fancier the
compiler tries to get, the more likely it is that something will go wrong.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/99ec94a6-ae8a-4848-81b5-44e9c75be54e%40isocpp.org.
------=_Part_18120_1775271743.1530329009827
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 29, 2018 at 10:10:33 PM UTC-4, Mingxin Wan=
g wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Sa=
turday, June 30, 2018 at 9:09:21 AM UTC+8, Nicol Bolas wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr">On Friday, June 29, 2018 at 9:03=
:26 PM UTC-4, Mingxin Wang wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div>By saying "I am also wondering if this concept cou=
ld help in generating default move constructors", I am thinking of the=
possibility to make "swap" a primitive, in other words, to make =
"swap beneath move", and the generated move constructors are alwa=
ys=C2=A0exception-safe.<br></div></div></blockquote><div><br></div><div>Tha=
t would not have that effect. A type with a throwing move constructor is on=
e that cannot be empty, and therefore allocates state even if it is empty. =
The classic example being `std::list` implementations that are required to =
have a single node. Your "swap primitive" wouldn't be able to=
allocate that memory, so it could not use that implementation.</div></div>=
</blockquote><div><br></div><div>I do not see the difference between alloca=
ting constructions and non-allocating constructions. Generating move constr=
uctors with `swap` requires the types to be trivially swappable and default=
constructible, rather than trivially default constructible. Thus I think t=
he move constructor of `std::list`=C2=A0can theoretically be generated with=
`swap`.</div></div></blockquote><div><br></div><div>It could, but it still=
wouldn't be noexcept because `std::list`'s default constructor is =
not noexcept. Or more specifically, it is not required to be.</div><div><br=
></div><div>So you've gained nothing.</div><div><br></div><div>Also, tr=
ivial swapping should not require default constructible. The whole point of=
trivial-anyability is that it can be done via memcpy of bytes. So a trivia=
l swap should be able to work through a byte array.</div><div><br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Compiler-generated=
move constructors are always as exception-safe as the move constructors th=
ey call. And your feature here can't change that.<br></div></div></bloc=
kquote><div><br></div><div>You are right about that. However, the default c=
onstructors are not always correct, e.g. for `std::unique_ptr`, because the=
re is a chance for the default move constructors to have different semantic=
s from other hand-written constructors. Generating move constructors with `=
swap` could avoid such abuse.</div></div></blockquote><div><br></div><div>T=
he ability of hand-written constructors to have different behavior from def=
ault constructors is not "abuse". It's why you can write move=
constructors at all.</div><div><br></div><div>Default move constructors sh=
ould not try to be fancy. They should provide very simple, very obvious sem=
antics: move each element. The fancier the compiler tries to get, the more =
likely it is that something will go wrong.<br></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/99ec94a6-ae8a-4848-81b5-44e9c75be54e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/99ec94a6-ae8a-4848-81b5-44e9c75be54e=
%40isocpp.org</a>.<br />
------=_Part_18120_1775271743.1530329009827--
------=_Part_18119_508097506.1530329009827--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Fri, 29 Jun 2018 20:58:06 -0700
Raw View
--000000000000d94780056fd3f8ff
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Fri, Jun 29, 2018 at 5:58 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Friday, June 29, 2018 at 6:51:12 PM UTC-4, Arthur O'Dwyer wrote:
>>
>> On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman wro=
te:
>>>
>>> How does this interface with the concept of relocatable? One would thin=
k
>>> relocatable implies trivially swappable, same as noexcept movable impli=
es
>>> noexcept swappable.
>>>
>>
>> In my C++Now 2018 talk on "trivially relocatable,"
>> <https://www.youtube.com/watch?v=3DMWBfmmg8-Yo> I promised in the outlin=
e
>> to talk about its relationship to "trivially swappable," and then did no=
t
>> actually do so =E2=80=94 sorry!
>> Essentially, yes, if a type is trivially relocatable then it intuitively
>> ought to be considered trivially swappable. However, there are two mino=
r
>> caveats that I can think of off the top of my head (and the reason I did=
n't
>> talk about it at C++Now is that I haven't thought about it much, and the
>> reason for *that* is that I don't have a motivating use-case).
>>
>> Caveat (A): Trivial relocation can be optimized into memcpy() or
>> memmove(). Trivial swap cannot be optimized into mem-anything, because
>> there is no libc primitive for *swapping* arrays of bytes. We could
>> certainly propose to add a __builtin_memswap() that would perform the sw=
ap
>> "in-place" in cache-line-sized blocks, but I'm not aware of any proposal=
s
>> nor prior art in that area.
>>
>
> void trivial_swap(T &a, T &b)
> {
> std::byte buff[sizeof(T)];
> memcpy(buff, &a, sizeof(T));
> memcpy(&a, &b, sizeof(T)); //b is no longer valid.
> memcpy(&b, buff, sizeof(T)); //b is valid again.
> }
>
> I believe the validity of this code naturally falls out of a type being
> TriviallyRelocatable.
>
Correct. What you've written there seems like essentially the same thing
you'd get from the unconstrained std::swap template after optimization,
which is why I went on to say that it didn't seem like the cost/benefit was
there for small objects. (And, as I wrote, for large objects trivial swap
cannot be optimized into mem-anything, because there is no libc primitive
for swapping arrays of bytes.)
However, I just went and checked Godbolt, and in fact both GCC and Clang *d=
o
have real trouble* optimizing the unconstrained std::swap template for
unique_ptr!
https://godbolt.org/g/noUP4k
So the benefit in practice (to specializing std::swap for trivially
relocatable types) would at least be *non-zero*.
But I'd still want to see a use-case that measurably benefits from an
O(1)-faster swap operation.
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0JHnTMSonc3KsEjcsQOBP1nPPG%3Datzj_wwHcAiwU=
2sW2Q%40mail.gmail.com.
--000000000000d94780056fd3f8ff
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Fri, Jun 29, 2018 at 5:58 PM, Nicol Bolas <span dir=3D"=
ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson=
@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:r=
gb(204,204,204);padding-left:1ex"><div dir=3D"ltr">On Friday, June 29, 2018=
at 6:51:12 PM UTC-4, Arthur O'Dwyer wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-s=
tyle:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D=
"ltr">On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"auto">How does this interface with the c=
oncept of relocatable? One would think relocatable implies trivially swappa=
ble, same as noexcept movable implies noexcept swappable.</div></blockquote=
><div><br></div><div>In <a href=3D"https://www.youtube.com/watch?v=3DMWBfmm=
g8-Yo" rel=3D"nofollow" target=3D"_blank">my C++Now 2018 talk on "triv=
ially relocatable,"</a> I promised in the outline to talk about its re=
lationship to "trivially swappable," and then did not actually do=
so =E2=80=94 sorry!</div><div>Essentially, yes, if a type is trivially rel=
ocatable then it intuitively ought to be considered trivially swappable.=C2=
=A0 However, there are two minor caveats that I can think of off the top of=
my head (and the reason I didn't talk about it at C++Now is that I hav=
en't thought about it much, and the reason for *that* is that I don'=
;t have a motivating use-case).</div><div><br></div><div>Caveat (A): Trivia=
l relocation can be optimized into memcpy() or memmove().=C2=A0 Trivial swa=
p cannot be optimized into mem-anything, because there is no libc primitive=
for <i>swapping</i> arrays of bytes. We could certainly propose to add a _=
_builtin_memswap() that would perform the swap "in-place" in cach=
e-line-sized blocks, but I'm not aware of any proposals nor prior art i=
n that area.</div></div></blockquote><div><br></div><div style=3D"backgroun=
d-color:rgb(250,250,250);border:1px solid rgb(187,187,187)" class=3D"gmail-=
m_5672037730267461838prettyprint"><code class=3D"gmail-m_567203773026746183=
8prettyprint"><div class=3D"gmail-m_5672037730267461838subprettyprint"><spa=
n style=3D"color:rgb(0,0,136)" class=3D"gmail-m_5672037730267461838styled-b=
y-prettify">void</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_56=
72037730267461838styled-by-prettify"> trivial_swap</span><span style=3D"col=
or:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">=
(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_56720377302674618=
38styled-by-prettify">T </span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_5672037730267461838styled-by-prettify">&</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettif=
y">a</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730=
267461838styled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=
=3D"gmail-m_5672037730267461838styled-by-prettify"> T </span><span style=3D=
"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-by-pretti=
fy">&</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_567203773=
0267461838styled-by-prettify">b</span><span style=3D"color:rgb(102,102,0)" =
class=3D"gmail-m_5672037730267461838styled-by-prettify">)</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettif=
y"><br></span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037=
730267461838styled-by-prettify">{</span><span style=3D"color:rgb(0,0,0)" cl=
ass=3D"gmail-m_5672037730267461838styled-by-prettify"><br>=C2=A0 std</span>=
<span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838st=
yled-by-prettify">::</span><span style=3D"color:rgb(0,0,136)" class=3D"gmai=
l-m_5672037730267461838styled-by-prettify">byte</span><span style=3D"color:=
rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify"> buff</=
span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461=
838styled-by-prettify">[</span><span style=3D"color:rgb(0,0,136)" class=3D"=
gmail-m_5672037730267461838styled-by-prettify">sizeof</span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-by-prettif=
y">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_56720377302674=
61838styled-by-prettify">T</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_5672037730267461838styled-by-prettify">)];</span><span style=3D=
"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">=
<br>=C2=A0 memcpy</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail=
-m_5672037730267461838styled-by-prettify">(</span><span style=3D"color:rgb(=
0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">buff</span>=
<span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838st=
yled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m=
_5672037730267461838styled-by-prettify"> </span><span style=3D"color:rgb(10=
2,102,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">&</sp=
an><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838sty=
led-by-prettify">a</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-m_5672037730267461838styled-by-prettify">,</span><span style=3D"color:rgb=
(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify"> </span><s=
pan style=3D"color:rgb(0,0,136)" class=3D"gmail-m_5672037730267461838styled=
-by-prettify">sizeof</span><span style=3D"color:rgb(102,102,0)" class=3D"gm=
ail-m_5672037730267461838styled-by-prettify">(</span><span style=3D"color:r=
gb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">T</span>=
<span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838st=
yled-by-prettify">));</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail=
-m_5672037730267461838styled-by-prettify"><br>=C2=A0 memcpy</span><span sty=
le=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-by-p=
rettify">(&</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_567=
2037730267461838styled-by-prettify">a</span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">,</span><span=
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-p=
rettify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672=
037730267461838styled-by-prettify">&</span><span style=3D"color:rgb(0,0=
,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">b</span><span =
style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-b=
y-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_56720=
37730267461838styled-by-prettify"> </span><span style=3D"color:rgb(0,0,136)=
" class=3D"gmail-m_5672037730267461838styled-by-prettify">sizeof</span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled=
-by-prettify">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_567=
2037730267461838styled-by-prettify">T</span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">));</span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by=
-prettify"> </span><span style=3D"color:rgb(136,0,0)" class=3D"gmail-m_5672=
037730267461838styled-by-prettify">//b is no longer valid.</span><span styl=
e=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-pretti=
fy"><br>=C2=A0 memcpy</span><span style=3D"color:rgb(102,102,0)" class=3D"g=
mail-m_5672037730267461838styled-by-prettify">(&</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">b<=
/span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_567203773026746=
1838styled-by-prettify">,</span><span style=3D"color:rgb(0,0,0)" class=3D"g=
mail-m_5672037730267461838styled-by-prettify"> buff</span><span style=3D"co=
lor:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify"=
>,</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461=
838styled-by-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"=
gmail-m_5672037730267461838styled-by-prettify">sizeof</span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838styled-by-prettif=
y">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_56720377302674=
61838styled-by-prettify">T</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_5672037730267461838styled-by-prettify">));</span><span style=3D=
"color:rgb(0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify">=
</span><span style=3D"color:rgb(136,0,0)" class=3D"gmail-m_567203773026746=
1838styled-by-prettify">//b is valid again.</span><span style=3D"color:rgb(=
0,0,0)" class=3D"gmail-m_5672037730267461838styled-by-prettify"><br></span>=
<span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5672037730267461838st=
yled-by-prettify">}</span></div></code></div><div><br></div><div>I believe =
the validity of this code naturally falls out of a type being TriviallyRelo=
catable.</div></div></blockquote><div><br></div><div>Correct. What you'=
ve written there seems like essentially the same thing you'd get from t=
he unconstrained std::swap template after optimization, which is why I went=
on to say that it didn't seem like the cost/benefit was there for smal=
l objects. (And, as I wrote, for large objects trivial swap cannot be optim=
ized into mem-anything, because there is no libc primitive for=C2=A0swappin=
g=C2=A0arrays of bytes.)</div><div><br></div><div>However, I just went and =
checked Godbolt, and in fact both GCC and Clang <i>do have real trouble</i>=
optimizing the unconstrained std::swap template for unique_ptr!</div><div>=
<a href=3D"https://godbolt.org/g/noUP4k">https://godbolt.org/g/noUP4k</a></=
div><div>So the benefit in practice (to specializing std::swap for triviall=
y relocatable types) would at least be <i>non-zero</i>.</div><div>But I'=
;d still want to see a use-case that measurably benefits from an O(1)-faste=
r swap operation.</div><div><br></div><div>=E2=80=93Arthur</div></div></div=
></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0JHnTMSonc3KsEjcsQOBP1nPPG%3Dat=
zj_wwHcAiwU2sW2Q%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0JHnTMSon=
c3KsEjcsQOBP1nPPG%3Datzj_wwHcAiwU2sW2Q%40mail.gmail.com</a>.<br />
--000000000000d94780056fd3f8ff--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 29 Jun 2018 21:18:44 -0700 (PDT)
Raw View
------=_Part_18584_1116090276.1530332324464
Content-Type: multipart/alternative;
boundary="----=_Part_18585_1070005874.1530332324465"
------=_Part_18585_1070005874.1530332324465
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, June 29, 2018 at 11:58:09 PM UTC-4, Arthur O'Dwyer wrote:
>
> On Fri, Jun 29, 2018 at 5:58 PM, Nicol Bolas <jmck...@gmail.com=20
> <javascript:>> wrote:
>
>> On Friday, June 29, 2018 at 6:51:12 PM UTC-4, Arthur O'Dwyer wrote:
>>>
>>> On Friday, June 29, 2018 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman wr=
ote:
>>>>
>>>> How does this interface with the concept of relocatable? One would=20
>>>> think relocatable implies trivially swappable, same as noexcept movabl=
e=20
>>>> implies noexcept swappable.
>>>>
>>>
>>> In my C++Now 2018 talk on "trivially relocatable,"=20
>>> <https://www.youtube.com/watch?v=3DMWBfmmg8-Yo> I promised in the outli=
ne=20
>>> to talk about its relationship to "trivially swappable," and then did n=
ot=20
>>> actually do so =E2=80=94 sorry!
>>> Essentially, yes, if a type is trivially relocatable then it intuitivel=
y=20
>>> ought to be considered trivially swappable. However, there are two min=
or=20
>>> caveats that I can think of off the top of my head (and the reason I di=
dn't=20
>>> talk about it at C++Now is that I haven't thought about it much, and th=
e=20
>>> reason for *that* is that I don't have a motivating use-case).
>>>
>>> Caveat (A): Trivial relocation can be optimized into memcpy() or=20
>>> memmove(). Trivial swap cannot be optimized into mem-anything, because=
=20
>>> there is no libc primitive for *swapping* arrays of bytes. We could=20
>>> certainly propose to add a __builtin_memswap() that would perform the s=
wap=20
>>> "in-place" in cache-line-sized blocks, but I'm not aware of any proposa=
ls=20
>>> nor prior art in that area.
>>>
>>
>> void trivial_swap(T &a, T &b)
>> {
>> std::byte buff[sizeof(T)];
>> memcpy(buff, &a, sizeof(T));
>> memcpy(&a, &b, sizeof(T)); //b is no longer valid.
>> memcpy(&b, buff, sizeof(T)); //b is valid again.
>> }
>>
>> I believe the validity of this code naturally falls out of a type being=
=20
>> TriviallyRelocatable.
>>
>
> Correct. What you've written there seems like essentially the same thing=
=20
> you'd get from the unconstrained std::swap template after optimization,=
=20
> which is why I went on to say that it didn't seem like the cost/benefit w=
as=20
> there for small objects. (And, as I wrote, for large objects trivial swap=
=20
> cannot be optimized into mem-anything, because there is no libc primitive=
=20
> for swapping arrays of bytes.)
>
> However, I just went and checked Godbolt, and in fact both GCC and Clang =
*do=20
> have real trouble* optimizing the unconstrained std::swap template for=20
> unique_ptr!
> https://godbolt.org/g/noUP4k
> So the benefit in practice (to specializing std::swap for trivially=20
> relocatable types) would at least be *non-zero*.
> But I'd still want to see a use-case that measurably benefits from an=20
> O(1)-faster swap operation.
>
> =E2=80=93Arthur
>
The OP is attempting to avoid indirect calls during swapping of type-erased=
=20
objects with small storage buffers. That's the use case. Swaps would be=20
cheap if the object always contained a pointer to heap allocated memory.=20
But with small storage optimization, that's not possible. If the object=20
lives in the small storage buffer, then you have to call its move=20
constructor.
So just look at the code for swapping `any` objects. It's not pretty.=20
<https://godbolt.org/g/KwZbnB>
The goal of this notion is to restore the ability to have cheap swapping.
Now granted, TriviallyRelocatable gives him exactly what he wants. So I=20
don't see a need for yet another Trivially-whatever concept.
Oh, and BTW: the alignas part on your byte buffer isn't necessary; trivial=
=20
copy operations to an array of bytes don't have to be aligned to the=20
alignment of the original object. That only matters if you're copying into=
=20
an object of the appropriate type.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/6d6b45bf-c591-4046-a95a-d391a16886d4%40isocpp.or=
g.
------=_Part_18585_1070005874.1530332324465
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 29, 2018 at 11:58:09 PM UTC-4, Arthur O=
9;Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
>On Fri, Jun 29, 2018 at 5:58 PM, Nicol Bolas <span dir=3D"ltr"><<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"E1cUckg4CAAJ" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tru=
e;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@gmai=
l.com</a>></span> wrote:<br><div><div class=3D"gmail_quote"><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr">On Friday, June 29, 2018 at 6:51:12 PM UTC-4, Arthur =
O'Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:=
rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">On Friday, June 29, 201=
8 at 1:56:01 AM UTC-7, Ga=C5=A1per A=C5=BEman wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div d=
ir=3D"auto">How does this interface with the concept of relocatable? One wo=
uld think relocatable implies trivially swappable, same as noexcept movable=
implies noexcept swappable.</div></blockquote><div><br></div><div>In <a hr=
ef=3D"https://www.youtube.com/watch?v=3DMWBfmmg8-Yo" rel=3D"nofollow" targe=
t=3D"_blank" onmousedown=3D"this.href=3D'https://www.youtube.com/watch?=
v\x3dMWBfmmg8-Yo';return true;" onclick=3D"this.href=3D'https://www=
..youtube.com/watch?v\x3dMWBfmmg8-Yo';return true;">my C++Now 2018 talk =
on "trivially relocatable,"</a> I promised in the outline to talk=
about its relationship to "trivially swappable," and then did no=
t actually do so =E2=80=94 sorry!</div><div>Essentially, yes, if a type is =
trivially relocatable then it intuitively ought to be considered trivially =
swappable.=C2=A0 However, there are two minor caveats that I can think of o=
ff the top of my head (and the reason I didn't talk about it at C++Now =
is that I haven't thought about it much, and the reason for *that* is t=
hat I don't have a motivating use-case).</div><div><br></div><div>Cavea=
t (A): Trivial relocation can be optimized into memcpy() or memmove().=C2=
=A0 Trivial swap cannot be optimized into mem-anything, because there is no=
libc primitive for <i>swapping</i> arrays of bytes. We could certainly pro=
pose to add a __builtin_memswap() that would perform the swap "in-plac=
e" in cache-line-sized blocks, but I'm not aware of any proposals =
nor prior art in that area.</div></div></blockquote><div><br></div><div sty=
le=3D"background-color:rgb(250,250,250);border:1px solid rgb(187,187,187)">=
<code><div><span style=3D"color:rgb(0,0,136)">void</span><span style=3D"col=
or:rgb(0,0,0)"> trivial_swap</span><span style=3D"color:rgb(102,102,0)">(</=
span><span style=3D"color:rgb(0,0,0)">T </span><span style=3D"color:rgb(102=
,102,0)">&</span><span style=3D"color:rgb(0,0,0)">a</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> T </spa=
n><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"color:rgb=
(0,0,0)">b</span><span style=3D"color:rgb(102,102,0)">)</span><span style=
=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</sp=
an><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 std</span><span style=3D"col=
or:rgb(102,102,0)">::</span><span style=3D"color:rgb(0,0,136)">byte</span><=
span style=3D"color:rgb(0,0,0)"> buff</span><span style=3D"color:rgb(102,10=
2,0)">[</span><span style=3D"color:rgb(0,0,136)">sizeof</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">T</span>=
<span style=3D"color:rgb(102,102,0)">)];</span><span style=3D"color:rgb(0,0=
,0)"><br>=C2=A0 memcpy</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(0,0,0)">buff</span><span style=3D"color:rgb(102,102=
,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:=
rgb(102,102,0)">&</span><span style=3D"color:rgb(0,0,0)">a</span><span =
style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(0,0,136)">sizeof</span><span style=3D"color:r=
gb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">T</span><span style=
=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br>=
=C2=A0 memcpy</span><span style=3D"color:rgb(102,102,0)">(&</span><span=
style=3D"color:rgb(0,0,0)">a</span><span style=3D"color:rgb(102,102,0)">,<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102=
,102,0)">&</span><span style=3D"color:rgb(0,0,0)">b</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(0,0,136)">sizeof</span><span style=3D"color:rgb(10=
2,102,0)">(</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"c=
olor:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"> </span><sp=
an style=3D"color:rgb(136,0,0)">//b is no longer valid.</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 memcpy</span><span style=3D"color:rgb(102,=
102,0)">(&</span><span style=3D"color:rgb(0,0,0)">b</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> buff</s=
pan><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,0,136)">sizeof</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">T</span>=
<span style=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0=
,0)"> </span><span style=3D"color:rgb(136,0,0)">//b is valid again.</span><=
span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102=
,0)">}</span></div></code></div><div><br></div><div>I believe the validity =
of this code naturally falls out of a type being TriviallyRelocatable.</div=
></div></blockquote><div><br></div><div>Correct. What you've written th=
ere seems like essentially the same thing you'd get from the unconstrai=
ned std::swap template after optimization, which is why I went on to say th=
at it didn't seem like the cost/benefit was there for small objects. (A=
nd, as I wrote, for large objects trivial swap cannot be optimized into mem=
-anything, because there is no libc primitive for=C2=A0swapping=C2=A0arrays=
of bytes.)</div><div><br></div><div>However, I just went and checked Godbo=
lt, and in fact both GCC and Clang <i>do have real trouble</i> optimizing t=
he unconstrained std::swap template for unique_ptr!</div><div><a href=3D"ht=
tps://godbolt.org/g/noUP4k" target=3D"_blank" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.=
org%2Fg%2FnoUP4k\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEkMOF7g3FgtDEdCYk_=
C2KbUt-doQ';return true;" onclick=3D"this.href=3D'https://www.googl=
e.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FnoUP4k\x26sa\x3dD\x26sntz\x3=
d1\x26usg\x3dAFQjCNEkMOF7g3FgtDEdCYk_C2KbUt-doQ';return true;">https://=
godbolt.org/g/noUP4k</a></div><div>So the benefit in practice (to specializ=
ing std::swap for trivially relocatable types) would at least be <i>non-zer=
o</i>.</div><div>But I'd still want to see a use-case that measurably b=
enefits from an O(1)-faster swap operation.</div><div><br></div><div>=E2=80=
=93Arthur</div></div></div></div></blockquote><div><br></div><div></div><di=
v>The OP is attempting to avoid indirect calls during swapping of type-eras=
ed objects with small storage buffers. That's the use case. Swaps would=
be cheap if the object always contained a pointer to heap allocated memory=
.. But with small storage optimization, that's not possible. If the obje=
ct lives in the small storage buffer, then you have to call its move constr=
uctor.</div><div><br></div><div>So just look at the code for swapping `any`=
objects.<a href=3D"https://godbolt.org/g/KwZbnB"> It's not pretty.</a>=
</div><div><br></div><div>The goal of this notion is to restore the ability=
to have cheap swapping.<br></div><div><br></div><div>Now granted, Triviall=
yRelocatable gives him exactly what he wants. So I don't see a need for=
yet another Trivially-whatever concept.</div><div><br></div><div>Oh, and B=
TW: the alignas part on your byte buffer isn't necessary; trivial copy =
operations to an array of bytes don't have to be aligned to the alignme=
nt of the original object. That only matters if you're copying into an =
object of the appropriate type.<br></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6d6b45bf-c591-4046-a95a-d391a16886d4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6d6b45bf-c591-4046-a95a-d391a16886d4=
%40isocpp.org</a>.<br />
------=_Part_18585_1070005874.1530332324465--
------=_Part_18584_1116090276.1530332324464--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 29 Jun 2018 22:32:50 -0700
Raw View
On Friday, 29 June 2018 18:04:50 PDT Nicol Bolas wrote:
> On Friday, June 29, 2018 at 6:08:10 PM UTC-4, Thiago Macieira wrote:
> > On Friday, 29 June 2018 00:19:40 PDT Mingxin Wang wrote:
> > > Informally, a type meets the *TriviallySwappable* requirements if the
> > > "std::swap" function overload of this type performs bitwise swap
> >
> > operation.
> >
> > Why do you need the concept? Why can't you just use std::swap for your
> > use-
> > case?
>
> He didn't really explain the problem very well. It's a performance issue,
> not a functionality issue.
Ok, so XY issue. He has a problem X (performance), he thinks he can solve it
with Y (concept) and asked about Y.
> Say you have a type-erased type like `any`. It's storing some type-erased
> value, and it's using small buffer optimization. If you move an `any`, and
> the stored object fits within the small buffer (like a `unique_ptr<T>`),
> then you can only move it by invoking `unique_ptr<T>`'s move constructor.
> This requires an indirect call through the type-erasure machinery.
Sorry, but why does it? Why can't there be a std::swap(std::any &, std::any &)
that knows that it can simply swap the internals, fast?
> A swap operation would require 3 of these moves. That's really slow.
>
> However, if the `any` could, at swap time, detect that its contents were
> TriviallySwappable, it could perform the swap with 3 memcpy operations.
std::any would know that its contents are trivially swappable without the need
for the concept. It knows that by design.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2028231.PPXpJpiaJL%40tjmaciei-mobl1.
.
Author: Mingxin Wang <wmx16835vv@163.com>
Date: Sat, 30 Jun 2018 02:47:20 -0700 (PDT)
Raw View
------=_Part_20321_131429242.1530352040867
Content-Type: multipart/alternative;
boundary="----=_Part_20322_692530476.1530352040867"
------=_Part_20322_692530476.1530352040867
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 30, 2018 at 1:32:55 PM UTC+8, Thiago Macieira wrote:
>
>
> > Say you have a type-erased type like `any`. It's storing some
> type-erased
> > value, and it's using small buffer optimization. If you move an `any`,
> and
> > the stored object fits within the small buffer (like a `unique_ptr<T>`),
> > then you can only move it by invoking `unique_ptr<T>`'s move
> constructor.
> > This requires an indirect call through the type-erasure machinery.
>
> Sorry, but why does it? Why can't there be a std::swap(std::any &,
> std::any &)
> that knows that it can simply swap the internals, fast?
>
In short, the problem is that: in order to stay compatible with
non-trivially-swappable objects, it would be difficult to implement
polymorphic facilities like `std::any` without dispatching of similar code
most of the time. If the polymorphic facilities no longer support
non-trivially-swappable objects, there will be a considerable performance
improvement without decline in practical usability.
> A swap operation would require 3 of these moves. That's really slow.
> >
> > However, if the `any` could, at swap time, detect that its contents were
> > TriviallySwappable, it could perform the swap with 3 memcpy operations.
>
> std::any would know that its contents are trivially swappable without the
> need
> for the concept. It knows that by design.
>
Yes, but as long as they support non-trivially-swappable ones on
construction, they could only know about the object at runtime when using
them.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/18c1586f-dcca-4e04-9ab6-0eb3e1ee06a5%40isocpp.org.
------=_Part_20322_692530476.1530352040867
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 30, 2018 at 1:32:55 PM UTC+8, Thiago Mac=
ieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><br>> Say you h=
ave a type-erased type like `any`. It's storing some type-erased
<br>> value, and it's using small buffer optimization. If you move a=
n `any`, and
<br>> the stored object fits within the small buffer (like a `unique_ptr=
<T>`),
<br>> then you can only move it by invoking `unique_ptr<T>`'s =
move constructor.
<br>> This requires an indirect call through the type-erasure machinery.
<br>
<br>Sorry, but why does it? Why can't there be a std::swap(std::any &am=
p;, std::any &)=20
<br>that knows that it can simply swap the internals, fast?
<br></blockquote><div><br></div><div>In short, the problem is that: in orde=
r to stay compatible with non-trivially-swappable objects, it would be diff=
icult to implement polymorphic facilities like `std::any` without dispatchi=
ng of similar code most of the time. If the polymorphic facilities no longe=
r support non-trivially-swappable objects, there will be a considerable per=
formance improvement without=C2=A0decline in practical usability.</div><div=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> A swap operati=
on would require 3 of these moves. That's really slow.
<br>>=20
<br>> However, if the `any` could, at swap time, detect that its content=
s were
<br>> TriviallySwappable, it could perform the swap with 3 memcpy operat=
ions.
<br>
<br>std::any would know that its contents are trivially swappable without t=
he need=20
<br>for the concept. It knows that by design.
<br></blockquote><div><br></div><div>Yes, but as long as they support non-t=
rivially-swappable ones on construction, they could only know about the obj=
ect at runtime when using them.</div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/18c1586f-dcca-4e04-9ab6-0eb3e1ee06a5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/18c1586f-dcca-4e04-9ab6-0eb3e1ee06a5=
%40isocpp.org</a>.<br />
------=_Part_20322_692530476.1530352040867--
------=_Part_20321_131429242.1530352040867--
.
Author: Mingxin Wang <wmx16835vv@163.com>
Date: Sat, 30 Jun 2018 03:10:49 -0700 (PDT)
Raw View
------=_Part_20590_85736250.1530353449734
Content-Type: multipart/alternative;
boundary="----=_Part_20591_1212672194.1530353449734"
------=_Part_20591_1212672194.1530353449734
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
After learning about your talk, I am pretty sure that the semantics of=20
"TriviallyRelocatable" is exactly what I want, and SBO in polymorphism=20
could be a strong motivation. Is there any paper on this concept? I think=
=20
the PFA (P0957) that I am currently working on will be a loyal referer.
On Saturday, June 30, 2018 at 11:58:09 AM UTC+8, Arthur O'Dwyer wrote:
>
> Correct. What you've written there seems like essentially the same thing=
=20
> you'd get from the unconstrained std::swap template after optimization,=
=20
> which is why I went on to say that it didn't seem like the cost/benefit w=
as=20
> there for small objects. (And, as I wrote, for large objects trivial swap=
=20
> cannot be optimized into mem-anything, because there is no libc primitive=
=20
> for swapping arrays of bytes.)
>
> However, I just went and checked Godbolt, and in fact both GCC and Clang =
*do=20
> have real trouble* optimizing the unconstrained std::swap template for=20
> unique_ptr!
> https://godbolt.org/g/noUP4k
> So the benefit in practice (to specializing std::swap for trivially=20
> relocatable types) would at least be *non-zero*.
> But I'd still want to see a use-case that measurably benefits from an=20
> O(1)-faster swap operation.
>
> =E2=80=93Arthur
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/141853af-30c2-4ef9-991a-fa9444706335%40isocpp.or=
g.
------=_Part_20591_1212672194.1530353449734
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>After learning about your talk, I am pretty sure that=
the semantics of "TriviallyRelocatable" is exactly=C2=A0what I w=
ant, and SBO in polymorphism could be a strong motivation. Is there any pap=
er on this concept? I think the PFA (P0957) that I am currently working on =
will be a loyal referer.</div><div><br></div>On Saturday, June 30, 2018 at =
11:58:09 AM UTC+8, Arthur O'Dwyer wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>Correct=
.. What you've written there seems like essentially the same thing you&#=
39;d get from the unconstrained std::swap template after optimization, whic=
h is why I went on to say that it didn't seem like the cost/benefit was=
there for small objects. (And, as I wrote, for large objects trivial swap =
cannot be optimized into mem-anything, because there is no libc primitive f=
or=C2=A0swapping=C2=A0arrays of bytes.)</div><div><br></div><div>However, I=
just went and checked Godbolt, and in fact both GCC and Clang <i>do have r=
eal trouble</i> optimizing the unconstrained std::swap template for unique_=
ptr!</div><div><a href=3D"https://godbolt.org/g/noUP4k" target=3D"_blank" r=
el=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url?=
q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FnoUP4k\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEkMOF7g3FgtDEdCYk_C2KbUt-doQ';return true;" onclick=3D"this.hr=
ef=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2Fn=
oUP4k\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEkMOF7g3FgtDEdCYk_C2KbUt-doQ&=
#39;;return true;">https://godbolt.org/g/noUP4k</a></div><div>So the benefi=
t in practice (to specializing std::swap for trivially relocatable types) w=
ould at least be <i>non-zero</i>.</div><div>But I'd still want to see a=
use-case that measurably benefits from an O(1)-faster swap operation.</div=
><div><br></div><div>=E2=80=93Arthur</div></div></div></div>
</blockquote></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/141853af-30c2-4ef9-991a-fa9444706335%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/141853af-30c2-4ef9-991a-fa9444706335=
%40isocpp.org</a>.<br />
------=_Part_20591_1212672194.1530353449734--
------=_Part_20590_85736250.1530353449734--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 30 Jun 2018 06:26:01 -0700 (PDT)
Raw View
------=_Part_21858_150888816.1530365162015
Content-Type: multipart/alternative;
boundary="----=_Part_21859_1097588556.1530365162015"
------=_Part_21859_1097588556.1530365162015
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 30, 2018 at 1:32:55 AM UTC-4, Thiago Macieira wrote:
>
> On Friday, 29 June 2018 18:04:50 PDT Nicol Bolas wrote:
> > On Friday, June 29, 2018 at 6:08:10 PM UTC-4, Thiago Macieira wrote:
> > > On Friday, 29 June 2018 00:19:40 PDT Mingxin Wang wrote:
> > > > Informally, a type meets the *TriviallySwappable* requirements if
> the
> > > > "std::swap" function overload of this type performs bitwise swap
> > >
> > > operation.
> > >
> > > Why do you need the concept? Why can't you just use std::swap for your
> > > use-
> > > case?
> >
> > He didn't really explain the problem very well. It's a performance
> issue,
> > not a functionality issue.
>
> Ok, so XY issue. He has a problem X (performance), he thinks he can solve
> it
> with Y (concept) and asked about Y.
>
Isn't every proposal an XY issue using that reasoning? That same XY issue
is why TriviallyCopyable exists.
> > Say you have a type-erased type like `any`. It's storing some
> type-erased
> > value, and it's using small buffer optimization. If you move an `any`,
> and
> > the stored object fits within the small buffer (like a `unique_ptr<T>`),
> > then you can only move it by invoking `unique_ptr<T>`'s move
> constructor.
> > This requires an indirect call through the type-erasure machinery.
>
> Sorry, but why does it? Why can't there be a std::swap(std::any &,
> std::any &)
> that knows that it can simply swap the internals, fast?
>
The TriviallyCopyable designation makes it legal for you to do byte-copies
of such objects. These are the *only* types where that is legal.
`unique_ptr<T>` is not TriviallyCopyable, but it is logically
TriviallySwappable. That is, given an understanding of how it's
implementation (and compilers) works, you ought to be able to do byte
copies between two objects of that type.
However, just because it "ought" to work doesn't mean it is legal by the
C++ standard. TriviallyCopyable is the only grouping where byte copying of
any form is allowed.
Furthermore, let's say that std::any can break the rules. Well, that would
only apply to standard library defined types. So if you tried to store a
non-standard type in `std::any`, it wouldn't be able to guess whether the
type was TriviallySwappable or not. Nor would users be able to write their
own type-erased types that can take advantage of that tool.
> A swap operation would require 3 of these moves. That's really slow.
> >
> > However, if the `any` could, at swap time, detect that its contents were
> > TriviallySwappable, it could perform the swap with 3 memcpy operations.
>
> std::any would know that its contents are trivially swappable without the
> need
> for the concept. It knows that by design.
>
It can't know that because "trivially swappable" isn't a thing. With no
standard-defined mechanism to key into, the only thing it could do is pick
a number of standard-defined types and declare that they fit the bill.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/da8e7f51-6380-4717-903b-79aac17b22e7%40isocpp.org.
------=_Part_21859_1097588556.1530365162015
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 30, 2018 at 1:32:55 AM UTC-4, Thiago Mac=
ieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Friday, 29 June=
2018 18:04:50 PDT Nicol Bolas wrote:
<br>> On Friday, June 29, 2018 at 6:08:10 PM UTC-4, Thiago Macieira wrot=
e:
<br>> > On Friday, 29 June 2018 00:19:40 PDT Mingxin Wang wrote:
<br>> > > Informally, a type meets the *TriviallySwappable* requir=
ements if the
<br>> > > "std::swap" function overload of this type per=
forms bitwise swap
<br>> >=20
<br>> > operation.
<br>> >=20
<br>> > Why do you need the concept? Why can't you just use std::=
swap for your
<br>> > use-
<br>> > case?
<br>>=20
<br>> He didn't really explain the problem very well. It's a per=
formance issue,
<br>> not a functionality issue.
<br>
<br>Ok, so XY issue. He has a problem X (performance), he thinks he can sol=
ve it=20
<br>with Y (concept) and asked about Y.<br></blockquote><div><br></div><div=
>Isn't every proposal an XY issue using that reasoning? That same XY is=
sue is why TriviallyCopyable exists.<br></div><div><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;">
<br>> Say you have a type-erased type like `any`. It's storing some =
type-erased
<br>> value, and it's using small buffer optimization. If you move a=
n `any`, and
<br>> the stored object fits within the small buffer (like a `unique_ptr=
<T>`),
<br>> then you can only move it by invoking `unique_ptr<T>`'s =
move constructor.
<br>> This requires an indirect call through the type-erasure machinery.
<br>
<br>Sorry, but why does it? Why can't there be a std::swap(std::any &am=
p;, std::any &)=20
<br>that knows that it can simply swap the internals, fast?<br></blockquote=
><div><br></div><div>The TriviallyCopyable designation makes it legal for y=
ou to do byte-copies of such objects. These are the <i>only</i> types where=
that is legal. `unique_ptr<T>` is not TriviallyCopyable, but it is l=
ogically TriviallySwappable. That is, given an understanding of how it'=
s implementation (and compilers) works, you ought to be able to do byte cop=
ies between two objects of that type.</div><div><br></div><div>However, jus=
t because it "ought" to work doesn't mean it is legal by the =
C++ standard. TriviallyCopyable is the only grouping where byte copying of =
any form is allowed.</div><div><br></div><div>Furthermore, let's say th=
at std::any can break the rules. Well, that would only apply to standard li=
brary defined types. So if you tried to store a non-standard type in `std::=
any`, it wouldn't be able to guess whether the type was TriviallySwappa=
ble or not. Nor would users be able to write their own type-erased types th=
at can take advantage of that tool.<br></div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;">
> A swap operation would require 3 of these moves. That's really slo=
w.
<br>>=20
<br>> However, if the `any` could, at swap time, detect that its content=
s were
<br>> TriviallySwappable, it could perform the swap with 3 memcpy operat=
ions.
<br>
<br>std::any would know that its contents are trivially swappable without t=
he need=20
<br>for the concept. It knows that by design.<br></blockquote><div><br></di=
v><div>It can't know that because "trivially swappable" isn&#=
39;t a thing. With no standard-defined mechanism to key into, the only thin=
g it could do is pick a number of standard-defined types and declare that t=
hey fit the bill.<br></div><br></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/da8e7f51-6380-4717-903b-79aac17b22e7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/da8e7f51-6380-4717-903b-79aac17b22e7=
%40isocpp.org</a>.<br />
------=_Part_21859_1097588556.1530365162015--
------=_Part_21858_150888816.1530365162015--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Sat, 30 Jun 2018 11:13:24 -0400
Raw View
> std::any would know that its contents are trivially swappable without the=
need=C2=A0
for the concept. It knows that by design
=E2=80=8EIf the type inside the any has a pointer to itself, you can't swap=
the bytes.
Sent=C2=A0from=C2=A0my=C2=A0BlackBerry=C2=A0portable=C2=A0Babbage=C2=A0Devi=
ce
=C2=A0 Original Message =C2=A0
From: Thiago Macieira
Sent: Saturday, June 30, 2018 1:32 AM
To: std-proposals@isocpp.org
Reply To: std-proposals@isocpp.org
Subject: Re: [std-proposals] Re: Better Performance in Polymorphic Programm=
ing: Trivially Swappable
On Friday, 29 June 2018 18:04:50 PDT Nicol Bolas wrote:
> On Friday, June 29, 2018 at 6:08:10 PM UTC-4, Thiago Macieira wrote:
> > On Friday, 29 June 2018 00:19:40 PDT Mingxin Wang wrote:
> > > Informally, a type meets the *TriviallySwappable* requirements if the
> > > "std::swap" function overload of this type performs bitwise swap
> >=20
> > operation.
> >=20
> > Why do you need the concept? Why can't you just use std::swap for your
> > use-
> > case?
>=20
> He didn't really explain the problem very well. It's a performance issue,
> not a functionality issue.
Ok, so XY issue. He has a problem X (performance), he thinks he can solve i=
t=20
with Y (concept) and asked about Y.
> Say you have a type-erased type like `any`. It's storing some type-erased
> value, and it's using small buffer optimization. If you move an `any`, an=
d
> the stored object fits within the small buffer (like a `unique_ptr<T>`),
> then you can only move it by invoking `unique_ptr<T>`'s move constructor.
> This requires an indirect call through the type-erasure machinery.
Sorry, but why does it? Why can't there be a std::swap(std::any &, std::any=
&)=20
that knows that it can simply swap the internals, fast?
> A swap operation would require 3 of these moves. That's really slow.
>=20
> However, if the `any` could, at swap time, detect that its contents were
> TriviallySwappable, it could perform the swap with 3 memcpy operations.
std::any would know that its contents are trivially swappable without the n=
eed=20
for the concept. It knows that by design.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/2028231.PPXpJpiaJL%40tjmaciei-mobl1.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/20180630151324.5218386.68840.56368%40gmail.com.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 30 Jun 2018 10:25:01 -0700 (PDT)
Raw View
------=_Part_23122_325647402.1530379501981
Content-Type: multipart/alternative;
boundary="----=_Part_23123_443316202.1530379501982"
------=_Part_23123_443316202.1530379501982
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 30, 2018 at 1:16:44 PM UTC-4, Thiago Macieira wrote:
>
> On Saturday, 30 June 2018 09:45:49 PDT Thiago Macieira wrote:
> > That's why I am saying this is QoI: the implementation can design it in
> such
> > a way. Or they can make different trade-offs, by saying that it will
> avoid
> > memory allocation but requiring then that there be a runtime dispatch in
> > order to do moves and swaps.
> >
> > Can we have the cake and eat it too? I like that idea.
>
> Actually, is this worth it? Maybe with a different example, other than
> std::any. I'd like to see such a concrete example.
>
> std::any can only be trivially swapped with another std::any if *both* are
> trivially swappable.
In the proposed implementation based on this concept, `std::any` would use
small buffer optimization only for types that are
TriviallySwappable/TriviallyRelocatable. Therefore, `std::any` itself would
be TriviallySwappable/TriviallyRelocatable, regardless of the type it holds.
And indeed, with this concept, we can *require* implementations of
`std::any` to be TriviallyRelocatable, and thus yoke the benefits of
employing that.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/68747c3a-e49b-440d-84c0-e637a3f33652%40isocpp.org.
------=_Part_23123_443316202.1530379501982
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 30, 2018 at 1:16:44 PM UTC-4, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Saturda=
y, 30 June 2018 09:45:49 PDT Thiago Macieira wrote:
<br>> That's why I am saying this is QoI: the implementation can des=
ign it in such
<br>> a way. Or they can make different trade-offs, by saying that it wi=
ll avoid
<br>> memory allocation but requiring then that there be a runtime dispa=
tch in
<br>> order to do moves and swaps.
<br>>=20
<br>> Can we have the cake and eat it too? I like that idea.
<br>
<br>Actually, is this worth it? Maybe with a different example, other than=
=20
<br>std::any. I'd like to see such a concrete example.
<br>
<br>std::any can only be trivially swapped with another std::any if *both* =
are=20
<br>trivially swappable.</blockquote><div><br></div><div>In the proposed im=
plementation based on this concept, `std::any` would use small buffer optim=
ization only for types that are TriviallySwappable/TriviallyRelocatable. Th=
erefore, `std::any` itself would be TriviallySwappable/TriviallyRelocatable=
, regardless of the type it holds.<br></div><div><br></div><div>And indeed,=
with this concept, we can <i>require</i> implementations of `std::any` to =
be TriviallyRelocatable, and thus yoke the benefits of employing that.</div=
></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/68747c3a-e49b-440d-84c0-e637a3f33652%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/68747c3a-e49b-440d-84c0-e637a3f33652=
%40isocpp.org</a>.<br />
------=_Part_23123_443316202.1530379501982--
------=_Part_23122_325647402.1530379501981--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 30 Jun 2018 10:30:05 -0700 (PDT)
Raw View
------=_Part_14996_1407335440.1530379805588
Content-Type: multipart/alternative;
boundary="----=_Part_14997_986006996.1530379805589"
------=_Part_14997_986006996.1530379805589
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Saturday, June 30, 2018 at 11:13:26 AM UTC-4, Tony V E wrote:
>
> > std::any would know that its contents are trivially swappable without=
=20
> the need =20
> for the concept. It knows that by design=20
>
> =E2=80=8EIf the type inside the any has a pointer to itself, you can't sw=
ap the=20
> bytes.=20
>
That's not entirely true. The type would have to have an *invariant* that=
=20
some pointer points to itself or a subobject thereof. It's OK to do a=20
memcpy of a TriviallyCopyable object that just so happens to be storing a=
=20
pointer to itself, because the result is exactly the same as if you had=20
done `auto T =3D other_object;`.
So in the case you're talking about, the type would have to have an=20
invariant such that when you perform a copy, the copy doesn't copy the=20
other object's pointer to itself. It initializes its own "itself" pointer=
=20
to point to itself.
In that case... such a type would not be=20
TriviallyRelocatable/TriviallySwappable (and if you designate your type as=
=20
such, you're lying and deserve what you get). Therefore, `std::any` would=
=20
not store it in the small buffer.
This is why TriviallyRelocatable is opt-in.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/bb3b0f2e-3ad1-4a27-8e43-e41b919be210%40isocpp.or=
g.
------=_Part_14997_986006996.1530379805589
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 30, 2018 at 11:13:26 AM UTC-4, T=
ony V E wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> std::any wo=
uld know that its contents are trivially swappable without the need=C2=A0
<br>for the concept. It knows that by design
<br>
<br>=E2=80=8EIf the type inside the any has a pointer to itself, you can=
9;t swap the bytes.
<br></blockquote><div><br></div><div>That's not entirely true. The type=
would have to have an <i>invariant</i> that some pointer points to itself =
or a subobject thereof. It's OK to do a memcpy of a TriviallyCopyable o=
bject that just so happens to be storing a pointer to itself, because the r=
esult is exactly the same as if you had done `auto T =3D other_object;`.</d=
iv><br><div></div><div>So in the case you're talking about, the type wo=
uld have to have an invariant such that when you perform a copy, the copy d=
oesn't copy the other object's pointer to itself. It initializes it=
s own "itself" pointer to point to itself.</div><div><br></div><d=
iv>In that case... such a type would not be TriviallyRelocatable/TriviallyS=
wappable (and if you designate your type as such, you're lying and dese=
rve what you get). Therefore, `std::any` would not store it in the small bu=
ffer.</div><div><br></div><div>This is why TriviallyRelocatable is opt-in.<=
br></div><br></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/bb3b0f2e-3ad1-4a27-8e43-e41b919be210%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/bb3b0f2e-3ad1-4a27-8e43-e41b919be210=
%40isocpp.org</a>.<br />
------=_Part_14997_986006996.1530379805589--
------=_Part_14996_1407335440.1530379805588--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 30 Jun 2018 10:31:39 -0700 (PDT)
Raw View
------=_Part_5408_1990019381.1530379899581
Content-Type: multipart/alternative;
boundary="----=_Part_5409_1120080148.1530379899582"
------=_Part_5409_1120080148.1530379899582
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 30, 2018 at 12:45:53 PM UTC-4, Thiago Macieira wrote:
>
> On Saturday, 30 June 2018 06:26:01 PDT Nicol Bolas wrote:
> > > std::any would know that its contents are trivially swappable without
> the
> > > need
> > > for the concept. It knows that by design.
> >
> > It can't know that because "trivially swappable" isn't a thing. With no
> > standard-defined mechanism to key into, the only thing it could do is
> pick
> > a number of standard-defined types and declare that they fit the bill.
>
> My point is that std::any can be designed in such a way that it knows by
> construction that it is always trivially swappable. A trivial
> implementation
> contains a pointer to a base class of polymorphic type that is derived for
> each hosted type. A pointer is trivially swappable, therefore std::any's
> swap() function is trivially swappable.
>
> That's why I am saying this is QoI: the implementation can design it in
> such a
> way. Or they can make different trade-offs, by saying that it will avoid
> memory allocation but requiring then that there be a runtime dispatch in
> order
> to do moves and swaps.
>
Or, we can get the best of both worlds by defining the concept of
TriviallySwapable. Or TriviallyRelocatable, since it turns out that this is
the same thing.
Can we have the cake and eat it too? I like that idea.
>
How is your suggestion having cake and eating it? With your way, an
implementation must pick one or the other. With the suggested solution, you
get both.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e12f29e5-9f8a-4388-95d0-745a40e59a0d%40isocpp.org.
------=_Part_5409_1120080148.1530379899582
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 30, 2018 at 12:45:53 PM UTC-4, T=
hiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Saturd=
ay, 30 June 2018 06:26:01 PDT Nicol Bolas wrote:
<br>> > std::any would know that its contents are trivially swappable=
without the
<br>> > need
<br>> > for the concept. It knows that by design.
<br>>=20
<br>> It can't know that because "trivially swappable" isn=
't a thing. With no
<br>> standard-defined mechanism to key into, the only thing it could do=
is pick
<br>> a number of standard-defined types and declare that they fit the b=
ill.
<br>
<br>My point is that std::any can be designed in such a way that it knows b=
y=20
<br>construction that it is always trivially swappable. A trivial implement=
ation=20
<br>contains a pointer to a base class of polymorphic type that is derived =
for=20
<br>each hosted type. A pointer is trivially swappable, therefore std::any&=
#39;s=20
<br>swap() function is trivially swappable.
<br>
<br>That's why I am saying this is QoI: the implementation can design i=
t in such a=20
<br>way. Or they can make different trade-offs, by saying that it will avoi=
d=20
<br>memory allocation but requiring then that there be a runtime dispatch i=
n order=20
<br>to do moves and swaps.<br></blockquote><div><br></div><div>Or, we can g=
et the best of both worlds by defining the concept of TriviallySwapable. Or=
TriviallyRelocatable, since it turns out that this is the same thing.</div=
><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
Can we have the cake and eat it too? I like that idea.
<br></blockquote><div><br></div><div>How is your suggestion having cake and=
eating it? With your way, an implementation must pick one or the other. Wi=
th the suggested solution, you get both.<br></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e12f29e5-9f8a-4388-95d0-745a40e59a0d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e12f29e5-9f8a-4388-95d0-745a40e59a0d=
%40isocpp.org</a>.<br />
------=_Part_5409_1120080148.1530379899582--
------=_Part_5408_1990019381.1530379899581--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 30 Jun 2018 09:45:49 -0700
Raw View
On Saturday, 30 June 2018 06:26:01 PDT Nicol Bolas wrote:
> > std::any would know that its contents are trivially swappable without the
> > need
> > for the concept. It knows that by design.
>
> It can't know that because "trivially swappable" isn't a thing. With no
> standard-defined mechanism to key into, the only thing it could do is pick
> a number of standard-defined types and declare that they fit the bill.
My point is that std::any can be designed in such a way that it knows by
construction that it is always trivially swappable. A trivial implementation
contains a pointer to a base class of polymorphic type that is derived for
each hosted type. A pointer is trivially swappable, therefore std::any's
swap() function is trivially swappable.
That's why I am saying this is QoI: the implementation can design it in such a
way. Or they can make different trade-offs, by saying that it will avoid
memory allocation but requiring then that there be a runtime dispatch in order
to do moves and swaps.
Can we have the cake and eat it too? I like that idea.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1781418.hVccNa2JWX%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 30 Jun 2018 10:16:40 -0700
Raw View
On Saturday, 30 June 2018 09:45:49 PDT Thiago Macieira wrote:
> That's why I am saying this is QoI: the implementation can design it in such
> a way. Or they can make different trade-offs, by saying that it will avoid
> memory allocation but requiring then that there be a runtime dispatch in
> order to do moves and swaps.
>
> Can we have the cake and eat it too? I like that idea.
Actually, is this worth it? Maybe with a different example, other than
std::any. I'd like to see such a concrete example.
std::any can only be trivially swapped with another std::any if *both* are
trivially swappable. And in the case we're discussing, you can only determine
if they are at runtime anyway. Therefore, doing swaps in an array of std::any
cannot be vectorised anyway and must be done for each element, with a dynamic
check of the trait.
So I ask again: is it worth storing this trait? Since std::any needs to check
dynamically what type it has, it may as well simply do the type-erased
swapping on its own.
If we take the example of std::array<std::unique_ptr<T>>, then std::array's
swap function calls unique_ptr's, which knows its internals and knows whether
it can trivially swap them. In the obvious implementation of std::unique_ptr,
swapping is trivial: just swap two pointers. That means the whole array's swap
is just swapping pointers and the compiler can optimise this.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8601611.sq9919Ay7g%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 30 Jun 2018 09:41:13 -0700
Raw View
On Saturday, 30 June 2018 02:47:20 PDT Mingxin Wang wrote:
> > > This requires an indirect call through the type-erasure machinery.
> >
> > Sorry, but why does it? Why can't there be a std::swap(std::any &,
> > std::any &)
> > that knows that it can simply swap the internals, fast?
>
> In short, the problem is that: in order to stay compatible with
> non-trivially-swappable objects, it would be difficult to implement
> polymorphic facilities like `std::any` without dispatching of similar code
> most of the time. If the polymorphic facilities no longer support
> non-trivially-swappable objects, there will be a considerable performance
> improvement without decline in practical usability.
Please give an actual example. I can't see what you're trying to do.
Note: do not include a memcpy of an object of a class with a virtual table.
Assume such classes are not trivially relocatable or swappable.
> > A swap operation would require 3 of these moves. That's really slow.
> >
> > > However, if the `any` could, at swap time, detect that its contents were
> > > TriviallySwappable, it could perform the swap with 3 memcpy operations.
> >
> > std::any would know that its contents are trivially swappable without the
> > need
> > for the concept. It knows that by design.
>
> Yes, but as long as they support non-trivially-swappable ones on
> construction, they could only know about the object at runtime when using
> them.
Sounds like QoI to me. std::any needs to use its internal storage only when at
compile time it can determine that the contents can be trivially relocated.
For anything else, it needs to use dynamic allocation, regardless of size.
That way, all std::any swaps will be trivial.
How it determines trivial relocatability is the topic of the discussion.
Currently, in standard C++, it requires a trivial type, as standard C++ does
not have something like Qt's Q_MOVABLE_TYPE.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/52775593.jh69NVt3cV%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 30 Jun 2018 13:51:23 -0700
Raw View
On Saturday, 30 June 2018 10:31:39 PDT Nicol Bolas wrote:
> > Can we have the cake and eat it too? I like that idea.
>
> How is your suggestion having cake and eating it? With your way, an
> implementation must pick one or the other. With the suggested solution, you
> get both.
It isn't. I meant to say that I am convinced there can be a better situation.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5548875.OCUxt60ss1%40tjmaciei-mobl1.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 30 Jun 2018 15:36:58 -0700 (PDT)
Raw View
------=_Part_14580_1873002111.1530398218296
Content-Type: multipart/alternative;
boundary="----=_Part_14581_1942486481.1530398218296"
------=_Part_14581_1942486481.1530398218296
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 30, 2018 at 4:51:26 PM UTC-4, Thiago Macieira wrote:
>
> On Saturday, 30 June 2018 10:31:39 PDT Nicol Bolas wrote:
> > > Can we have the cake and eat it too? I like that idea.
> >
> > How is your suggestion having cake and eating it? With your way, an
> > implementation must pick one or the other. With the suggested solution,
> you
> > get both.
>
> It isn't. I meant to say that I am convinced there can be a better
> situation.
>
Well, it turns out that the OP really just wants TriviallyRelocatable,
which adequately solves his problem. So we already have a better solution:
build the infrastructure needed for TriviallyRelocatable, and we solve this
problem and plenty of others.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/50612651-618f-46b3-94cc-17dcab771d89%40isocpp.org.
------=_Part_14581_1942486481.1530398218296
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 30, 2018 at 4:51:26 PM UTC-4, Thiago Mac=
ieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Saturday, 30 Ju=
ne 2018 10:31:39 PDT Nicol Bolas wrote:
<br>> > Can we have the cake and eat it too? I like that idea.
<br>>=20
<br>> How is your suggestion having cake and eating it? With your way, a=
n
<br>> implementation must pick one or the other. With the suggested solu=
tion, you
<br>> get both.
<br>
<br>It isn't. I meant to say that I am convinced there can be a better =
situation.
<br></blockquote><div><br></div><div>Well, it turns out that the OP really =
just wants TriviallyRelocatable, which adequately solves his problem. So we=
already have a better solution: build the infrastructure needed for Trivia=
llyRelocatable, and we solve this problem and plenty of others.</div><br></=
div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/50612651-618f-46b3-94cc-17dcab771d89%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/50612651-618f-46b3-94cc-17dcab771d89=
%40isocpp.org</a>.<br />
------=_Part_14581_1942486481.1530398218296--
------=_Part_14580_1873002111.1530398218296--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 01 Jul 2018 07:47:52 -0700
Raw View
On Saturday, 30 June 2018 15:36:58 PDT Nicol Bolas wrote:
> Well, it turns out that the OP really just wants TriviallyRelocatable,
> which adequately solves his problem. So we already have a better solution:
> build the infrastructure needed for TriviallyRelocatable, and we solve this
> problem and plenty of others.
Agreed. Just note that trivial relocatability goes one step further than
destructive moves. With the latter, to implement a swap you'd still need three
actual calls.
And that trivial relocatability gives us the efficient memswap that Arthur
suggested, plus it could be implemented by regular library code.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4599942.hOtzgv335l%40tjmaciei-mobl1.
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Sun, 1 Jul 2018 23:45:16 -0700
Raw View
--000000000000638075056ffe8a1f
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
FYI, I just implemented this "check if trivially swappable, and if so,
trivially swap" optimization in a branch of SG14's stdext::inplace_function=
:
https://github.com/WG21-SG14/SG14/commit/e9bfae8?w=3D1
And then I realized that it *might* be better to stick with the "relocate"
primitive:
https://github.com/WG21-SG14/SG14/compare/203a411...de43f6e
But if this is *only* speeding up `swap`, then I still don't really see the
point. Is anyone motivated to do some kind of benchmark to prove that
"trivial swap" is a useful operation?
(Recall that I have *done* the benchmarks
<https://www.youtube.com/watch?v=3DMWBfmmg8-Yo&t=3D27m> to prove that "triv=
ial
relocate" is a useful operation, in non-type-erased contexts. What we're
looking for here is some special indication about
trivial-swap-in-terms-of-trivial-relocate.)
It occurs to me that "trivial swap" might be useful to algorithms such as
std::sort, which can be based on swaps. But I'm not sure if those
algorithms currently work by swapping, or if they work by moving (in which
case they might be adjusted to work by trivially-relocating, in the
trivially relocatable case).
=E2=80=93Arthur
On Sun, Jul 1, 2018 at 7:47 AM, Thiago Macieira <thiago@macieira.org> wrote=
:
> On Saturday, 30 June 2018 15:36:58 PDT Nicol Bolas wrote:
> > Well, it turns out that the OP really just wants TriviallyRelocatable,
> > which adequately solves his problem. So we already have a better
> solution:
> > build the infrastructure needed for TriviallyRelocatable, and we solve
> this
> > problem and plenty of others.
>
> Agreed. Just note that trivial relocatability goes one step further than
> destructive moves. With the latter, to implement a swap you'd still need
> three
> actual calls.
>
> And that trivial relocatability gives us the efficient memswap that Arthu=
r
> suggested, plus it could be implemented by regular library code.
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0LT6uW6utFcR%3DeKiSfDAvHOfRnB%2BLEYrfHFLuy=
Oafu1ZA%40mail.gmail.com.
--000000000000638075056ffe8a1f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">FYI, I just implemented this "check if trivially swap=
pable, and if so, trivially swap" optimization in a branch of SG14'=
;s stdext::inplace_function:<div><a href=3D"https://github.com/WG21-SG14/SG=
14/commit/e9bfae8?w=3D1">https://github.com/WG21-SG14/SG14/commit/e9bfae8?w=
=3D1</a></div><div>And then I realized that it <i>might</i> be better to st=
ick with the "relocate" primitive:<br></div><div><a href=3D"https=
://github.com/WG21-SG14/SG14/compare/203a411...de43f6e">https://github.com/=
WG21-SG14/SG14/compare/203a411...de43f6e</a><br></div><div><br></div><div>B=
ut if this is <i>only</i> speeding up `swap`, then I still don't really=
see the point.=C2=A0 Is anyone motivated to do some kind of benchmark to p=
rove that "trivial swap" is a useful operation?</div><div><br></d=
iv><div>(Recall that <a href=3D"https://www.youtube.com/watch?v=3DMWBfmmg8-=
Yo&t=3D27m">I have <i>done</i> the benchmarks</a> to prove that "t=
rivial relocate" is a useful operation, in non-type-erased contexts. W=
hat we're looking for here is some special indication about trivial-swa=
p-in-terms-of-trivial-relocate.)</div><div><br></div><div>It occurs to me t=
hat "trivial swap" might be useful to algorithms such as std::sor=
t, which can be based on swaps. But I'm not sure if those algorithms cu=
rrently work by swapping, or if they work by moving (in which case they mig=
ht be adjusted to work by trivially-relocating, in the trivially relocatabl=
e case).</div><div><br></div><div>=E2=80=93Arthur</div><div><br></div><div>=
<br></div><div class=3D"gmail_extra"><div class=3D"gmail_quote">On Sun, Jul=
1, 2018 at 7:47 AM, Thiago Macieira <span dir=3D"ltr"><<a href=3D"mailt=
o:thiago@macieira.org" target=3D"_blank">thiago@macieira.org</a>></span>=
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><span class=3D"">On Saturday, 30 =
June 2018 15:36:58 PDT Nicol Bolas wrote:<br>
> Well, it turns out that the OP really just wants TriviallyRelocatable,=
<br>
> which adequately solves his problem. So we already have a better solut=
ion:<br>
> build the infrastructure needed for TriviallyRelocatable, and we solve=
this<br>
> problem and plenty of others.<br>
<br>
</span>Agreed. Just note that trivial relocatability goes one step further =
than <br>
destructive moves. With the latter, to implement a swap you'd still nee=
d three <br>
actual calls.<br>
<br>
And that trivial relocatability gives us the efficient memswap that Arthur =
<br>
suggested, plus it could be implemented by regular library code.<br></block=
quote></div></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0LT6uW6utFcR%3DeKiSfDAvHOfRnB%2=
BLEYrfHFLuyOafu1ZA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0LT6uW6=
utFcR%3DeKiSfDAvHOfRnB%2BLEYrfHFLuyOafu1ZA%40mail.gmail.com</a>.<br />
--000000000000638075056ffe8a1f--
.
Author: Mingxin Wang <wmx16835vv@163.com>
Date: Mon, 2 Jul 2018 03:29:45 -0700 (PDT)
Raw View
------=_Part_10706_990475624.1530527385281
Content-Type: multipart/alternative;
boundary="----=_Part_10707_257162789.1530527385282"
------=_Part_10707_257162789.1530527385282
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
After reading the code, I find the implementation was not exactly=20
consistent with what I imagine. I did not mean that the implementation=20
should not be compatible with non-trivially-relocatable types, but should=
=20
optimize for trivially-relocatable types. In order to clarify the=20
motivation, I made an illustrative example similar to `std::function`,=20
which is also the equivalent code expected to be generated with=20
`static_proxy<Callable<void>>` defined in the PFA (p0957).
#include <cstdio>
#include <utility>
#include <type_traits>
/**
* The definition of is_trivially_relocatable
* Let's assume that any move constructible type is trivially relocatable b=
y
* default.
*/
template <class T>
struct is_trivially_relocatable : std::is_move_constructible<T> {};
template <class T>
inline constexpr bool is_trivially_relocatable_v =3D
is_trivially_relocatable<T>::value;
/**
* The configuration of SBO and corresponding data structure
*/
inline constexpr std::size_t SBO_SIZE =3D sizeof(void*);
template <class T>
inline constexpr bool USE_SBO =3D
is_trivially_relocatable_v<T> &&
sizeof(T) <=3D SBO_SIZE &&
std::alignment_of_v<T> <=3D std::alignment_of_v<void*>;
union storage_t {
void* data_ptr_;
mutable char data_[SBO_SIZE];
};
/**
* A basic implementation for the dispatch specifically for Callable types
* Note that there is NO runtime overhead in checking whether a type is=20
suitable
* for SBO.
*/
template <class R, class... Args>
struct vtable_t {
public:
template <class T>
constexpr explicit vtable_t(std::in_place_type_t<T>)
: fun_(fun_impl<T>), destroy_(destroy_impl<T>) {}
R(*fun_)(storage_t&, Args&&...);
void(*destroy_)(storage_t&);
private:
template <class T>
static R fun_impl(storage_t& s, Args&&... args) {
if constexpr (USE_SBO<T>) {
return (*reinterpret_cast<T*>(s.data_))(std::forward<Args>(args)...);
} else {
return (*static_cast<T*>(s.data_ptr_))(std::forward<Args>(args)...);
}
}
template <class T>
static void destroy_impl(storage_t& s) {
if constexpr (USE_SBO<T>) {
reinterpret_cast<T*>(s.data_)->~T();
} else {
delete static_cast<T*>(s.data_ptr_);
}
}
};
/**
* Declare the value of the vtables
*/
template <class T, class R, class... Args>
inline constexpr vtable_t<R, Args...> VTABLE{std::in_place_type<T>};
/**
* A basic functionality defined by `std::function`
*/
template <class T>
class my_function;
template <class R, class... Args>
class my_function<R(Args...)> {
public:
/**
* An empty state of the vtable is not designed to keep the code simple
*/
my_function() : vtable_(nullptr) {}
template <class T>
my_function(T&& data) : my_function(std::in_place_type<std::decay_t<T>>,
std::forward<T>(data)) {}
template <class T, class... _Args>
explicit my_function(std::in_place_type_t<T>, _Args&&... args) {
if constexpr (USE_SBO<T>) {
new (reinterpret_cast<T*>(storage_.data_))=20
T(std::forward<_Args>(args)...);
} else {
storage_.data_ptr_ =3D new T(std::forward<_Args>(args)...);
}
vtable_ =3D &VTABLE<T, R, Args...>;
}
/**
* This is what I want: No dispatch when moving or swapping
* The code is correct because if the type is NOT trivially relocatable,=
=20
it
* will be stored on the heap, and its pointer is simply trivially=20
relocatable.
*/
my_function(my_function&& rhs) {
storage_ =3D rhs.storage_;
vtable_ =3D rhs.vtable_;
rhs.vtable_ =3D nullptr;
}
/**
* In order to keep the code simple, the copy constructor was not=20
implemented
*/
my_function(const my_function&) =3D delete;
~my_function() {
if (vtable_ !=3D nullptr) {
vtable_->destroy_(storage_);
}
}
R operator()(Args... args) {
vtable_->fun_(storage_, std::forward<Args>(args)...);
}
/**
* Performing bit-wise swap operation is OK!
*/
void swap(my_function& rhs) {
std::swap(storage_, rhs.storage_);
std::swap(vtable_, rhs.vtable_);
}
private:
storage_t storage_;
const vtable_t<R, Args...>* vtable_;
};
int main() {
my_function<void()> f([] { puts("lalala"); });
f();
auto g =3D std::move(f); // Nice!
g();
f.swap(g); // Nice!
f();
return 0;
}
The code works fine with latest gcc, clang and msvc.
Thank you!
Mingxin Wang
On Monday, July 2, 2018 at 2:45:20 PM UTC+8, Arthur O'Dwyer wrote:
>
> FYI, I just implemented this "check if trivially swappable, and if so,=20
> trivially swap" optimization in a branch of SG14's stdext::inplace_functi=
on:
> https://github.com/WG21-SG14/SG14/commit/e9bfae8?w=3D1
> And then I realized that it *might* be better to stick with the=20
> "relocate" primitive:
> https://github.com/WG21-SG14/SG14/compare/203a411...de43f6e
>
> But if this is *only* speeding up `swap`, then I still don't really see=
=20
> the point. Is anyone motivated to do some kind of benchmark to prove tha=
t=20
> "trivial swap" is a useful operation?
>
> (Recall that I have *done* the benchmarks=20
> <https://www.youtube.com/watch?v=3DMWBfmmg8-Yo&t=3D27m> to prove that=20
> "trivial relocate" is a useful operation, in non-type-erased contexts. Wh=
at=20
> we're looking for here is some special indication about=20
> trivial-swap-in-terms-of-trivial-relocate.)
>
> It occurs to me that "trivial swap" might be useful to algorithms such as=
=20
> std::sort, which can be based on swaps. But I'm not sure if those=20
> algorithms currently work by swapping, or if they work by moving (in whic=
h=20
> case they might be adjusted to work by trivially-relocating, in the=20
> trivially relocatable case).
>
> =E2=80=93Arthur
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/b6e92c1b-7556-4ca4-8cfa-1618cf5f02b5%40isocpp.or=
g.
------=_Part_10707_257162789.1530527385282
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">After reading the code, I find the implementation was not=
=C2=A0exactly consistent with what I imagine. I did not mean that the imple=
mentation should not be=C2=A0compatible with non-trivially-relocatable type=
s, but should optimize for trivially-relocatable types. In order to clarify=
the motivation, I made an illustrative example similar to `std::function`,=
which is also the equivalent code expected to be generated with `static_pr=
oxy<Callable<void>>` defined in the PFA (p0957).<div><br></div>=
<div><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 25=
0); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1p=
x; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpre=
ttyprint"><div class=3D"subprettyprint"><font color=3D"#660066">#include &l=
t;cstdio></font></div><div class=3D"subprettyprint"><font color=3D"#6600=
66"><br></font></div><div class=3D"subprettyprint"><font color=3D"#660066">=
#include <utility></font></div><div class=3D"subprettyprint"><font co=
lor=3D"#660066">#include <type_traits></font></div><div class=3D"subp=
rettyprint"><font color=3D"#660066"><br></font></div><div class=3D"subprett=
yprint"><font color=3D"#660066">/**</font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">=C2=A0* The definition of is_trivially_relocatab=
le</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0=
* Let's assume that any move constructible type is trivially relocatabl=
e by</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=
=A0* default.</font></div><div class=3D"subprettyprint"><font color=3D"#660=
066">=C2=A0*/</font></div><div class=3D"subprettyprint"><font color=3D"#660=
066">template <class T></font></div><div class=3D"subprettyprint"><fo=
nt color=3D"#660066">struct is_trivially_relocatable : std::is_move_constru=
ctible<T> {};</font></div><div class=3D"subprettyprint"><font color=
=3D"#660066"><br></font></div><div class=3D"subprettyprint"><font color=3D"=
#660066">template <class T></font></div><div class=3D"subprettyprint"=
><font color=3D"#660066">inline constexpr bool is_trivially_relocatable_v =
=3D</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=
=A0 =C2=A0 is_trivially_relocatable<T>::value;</font></div><div class=
=3D"subprettyprint"><font color=3D"#660066"><br></font></div><div class=3D"=
subprettyprint"><font color=3D"#660066">/**</font></div><div class=3D"subpr=
ettyprint"><font color=3D"#660066">=C2=A0* The configuration of SBO and cor=
responding data structure</font></div><div class=3D"subprettyprint"><font c=
olor=3D"#660066">=C2=A0*/</font></div><div class=3D"subprettyprint"><font c=
olor=3D"#660066">inline constexpr std::size_t SBO_SIZE =3D sizeof(void*);</=
font></div><div class=3D"subprettyprint"><font color=3D"#660066"><br></font=
></div><div class=3D"subprettyprint"><font color=3D"#660066">template <c=
lass T></font></div><div class=3D"subprettyprint"><font color=3D"#660066=
">inline constexpr bool USE_SBO =3D</font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">=C2=A0 =C2=A0 is_trivially_relocatable_v<T>=
; &&</font></div><div class=3D"subprettyprint"><font color=3D"#6600=
66">=C2=A0 =C2=A0 sizeof(T) <=3D SBO_SIZE &&</font></div><div cl=
ass=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 std::alignment=
_of_v<T> <=3D std::alignment_of_v<void*>;</font></div><div c=
lass=3D"subprettyprint"><font color=3D"#660066"><br></font></div><div class=
=3D"subprettyprint"><font color=3D"#660066">union storage_t {</font></div><=
div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 void* data_ptr_=
;</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =
mutable char data_[SBO_SIZE];</font></div><div class=3D"subprettyprint"><fo=
nt color=3D"#660066">};</font></div><div class=3D"subprettyprint"><font col=
or=3D"#660066"><br></font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">/**</font></div><div class=3D"subprettyprint"><font color=3D"#=
660066">=C2=A0* A basic implementation for the dispatch specifically for Ca=
llable types</font></div><div class=3D"subprettyprint"><font color=3D"#6600=
66">=C2=A0* Note that there is NO runtime overhead in checking whether a ty=
pe is suitable</font></div><div class=3D"subprettyprint"><font color=3D"#66=
0066">=C2=A0* for SBO.</font></div><div class=3D"subprettyprint"><font colo=
r=3D"#660066">=C2=A0*/</font></div><div class=3D"subprettyprint"><font colo=
r=3D"#660066">template <class R, class... Args></font></div><div clas=
s=3D"subprettyprint"><font color=3D"#660066">struct vtable_t {</font></div>=
<div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0public:</font><=
/div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 template =
<class T></font></div><div class=3D"subprettyprint"><font color=3D"#6=
60066">=C2=A0 constexpr explicit vtable_t(std::in_place_type_t<T>)</f=
ont></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=
=A0 =C2=A0 : fun_(fun_impl<T>), destroy_(destroy_impl<T>) {}</f=
ont></div><div class=3D"subprettyprint"><font color=3D"#660066"><br></font>=
</div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 R(*fun_)=
(storage_t&, Args&&...);</font></div><div class=3D"subprettypri=
nt"><font color=3D"#660066">=C2=A0 void(*destroy_)(storage_t&);</font><=
/div><div class=3D"subprettyprint"><font color=3D"#660066"><br></font></div=
><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0private:</font=
></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 templat=
e <class T></font></div><div class=3D"subprettyprint"><font color=3D"=
#660066">=C2=A0 static R fun_impl(storage_t& s, Args&&... args)=
{</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0=
=C2=A0 if constexpr (USE_SBO<T>) {</font></div><div class=3D"subpret=
typrint"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 return (*reinterpret_=
cast<T*>(s.data_))(std::forward<Args>(args)...);</font></div><d=
iv class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 } else {<=
/font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =
=C2=A0 =C2=A0 return (*static_cast<T*>(s.data_ptr_))(std::forward<=
Args>(args)...);</font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">=C2=A0 =C2=A0 }</font></div><div class=3D"subprettyprint"><fon=
t color=3D"#660066">=C2=A0 }</font></div><div class=3D"subprettyprint"><fon=
t color=3D"#660066"><br></font></div><div class=3D"subprettyprint"><font co=
lor=3D"#660066">=C2=A0 template <class T></font></div><div class=3D"s=
ubprettyprint"><font color=3D"#660066">=C2=A0 static void destroy_impl(stor=
age_t& s) {</font></div><div class=3D"subprettyprint"><font color=3D"#6=
60066">=C2=A0 =C2=A0 if constexpr (USE_SBO<T>) {</font></div><div cla=
ss=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 reinterp=
ret_cast<T*>(s.data_)->~T();</font></div><div class=3D"subprettypr=
int"><font color=3D"#660066">=C2=A0 =C2=A0 } else {</font></div><div class=
=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 delete sta=
tic_cast<T*>(s.data_ptr_);</font></div><div class=3D"subprettyprint">=
<font color=3D"#660066">=C2=A0 =C2=A0 }</font></div><div class=3D"subpretty=
print"><font color=3D"#660066">=C2=A0 }</font></div><div class=3D"subpretty=
print"><font color=3D"#660066">};</font></div><div class=3D"subprettyprint"=
><font color=3D"#660066"><br></font></div><div class=3D"subprettyprint"><fo=
nt color=3D"#660066">/**</font></div><div class=3D"subprettyprint"><font co=
lor=3D"#660066">=C2=A0* Declare the value of the vtables</font></div><div c=
lass=3D"subprettyprint"><font color=3D"#660066">=C2=A0*/</font></div><div c=
lass=3D"subprettyprint"><font color=3D"#660066">template <class T, class=
R, class... Args></font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">inline constexpr vtable_t<R, Args...> VTABLE{std::in_pla=
ce_type<T>};</font></div><div class=3D"subprettyprint"><font color=3D=
"#660066"><br></font></div><div class=3D"subprettyprint"><font color=3D"#66=
0066">/**</font></div><div class=3D"subprettyprint"><font color=3D"#660066"=
>=C2=A0* A basic functionality defined by `std::function`</font></div><div =
class=3D"subprettyprint"><font color=3D"#660066">=C2=A0*/</font></div><div =
class=3D"subprettyprint"><font color=3D"#660066">template <class T></=
font></div><div class=3D"subprettyprint"><font color=3D"#660066">class my_f=
unction;</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=
<br></font></div><div class=3D"subprettyprint"><font color=3D"#660066">temp=
late <class R, class... Args></font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">class my_function<R(Args...)> {</font></di=
v><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0public:</font=
></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 /**</fo=
nt></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=
=A0* An empty state of the vtable is not designed to keep the code simple</=
font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=
=A0*/</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=
=A0 my_function() : vtable_(nullptr) {}</font></div><div class=3D"subpretty=
print"><font color=3D"#660066"><br></font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">=C2=A0 template <class T></font></div><div=
class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 my_function(T&=
& data) : my_function(std::in_place_type<std::decay_t<T>>,<=
/font></div><div class=3D"subprettyprint"><font color=3D"#660066">=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 =C2=A0 =C2=A0 =C2=A0 std::forward<T>(=
data)) {}</font></div><div class=3D"subprettyprint"><font color=3D"#660066"=
><br></font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=
=A0 template <class T, class... _Args></font></div><div class=3D"subp=
rettyprint"><font color=3D"#660066">=C2=A0 explicit my_function(std::in_pla=
ce_type_t<T>, _Args&&... args) {</font></div><div class=3D"su=
bprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 if constexpr (USE_SBO&l=
t;T>) {</font></div><div class=3D"subprettyprint"><font color=3D"#660066=
">=C2=A0 =C2=A0 =C2=A0 new (reinterpret_cast<T*>(storage_.data_)) T(s=
td::forward<_Args>(args)...);</font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">=C2=A0 =C2=A0 } else {</font></div><div class=3D=
"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 storage_.data=
_ptr_ =3D new T(std::forward<_Args>(args)...);</font></div><div class=
=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 }</font></div><di=
v class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 vtable_ =
=3D &VTABLE<T, R, Args...>;</font></div><div class=3D"subprettypr=
int"><font color=3D"#660066">=C2=A0 }</font></div><div class=3D"subprettypr=
int"><font color=3D"#660066"><br></font></div><div class=3D"subprettyprint"=
><font color=3D"#660066">=C2=A0 /**</font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">=C2=A0 =C2=A0* This is what I want: No dispatch =
when moving or swapping</font></div><div class=3D"subprettyprint"><font col=
or=3D"#660066">=C2=A0 =C2=A0* The code is correct because if the type is NO=
T trivially relocatable, it</font></div><div class=3D"subprettyprint"><font=
color=3D"#660066">=C2=A0 =C2=A0* will be stored on the heap, and its point=
er is simply trivially relocatable.</font></div><div class=3D"subprettyprin=
t"><font color=3D"#660066">=C2=A0 =C2=A0*/</font></div><div class=3D"subpre=
ttyprint"><font color=3D"#660066">=C2=A0 my_function(my_function&& =
rhs) {</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=
=C2=A0 =C2=A0 storage_ =3D rhs.storage_;</font></div><div class=3D"subprett=
yprint"><font color=3D"#660066">=C2=A0 =C2=A0 vtable_ =3D rhs.vtable_;</fon=
t></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0=
rhs.vtable_ =3D nullptr;</font></div><div class=3D"subprettyprint"><font c=
olor=3D"#660066">=C2=A0 }</font></div><div class=3D"subprettyprint"><font c=
olor=3D"#660066"><br></font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">=C2=A0 /**</font></div><div class=3D"subprettyprint"><font col=
or=3D"#660066">=C2=A0 =C2=A0* In order to keep the code simple, the copy co=
nstructor was not implemented</font></div><div class=3D"subprettyprint"><fo=
nt color=3D"#660066">=C2=A0 =C2=A0*/</font></div><div class=3D"subprettypri=
nt"><font color=3D"#660066">=C2=A0 my_function(const my_function&) =3D =
delete;</font></div><div class=3D"subprettyprint"><font color=3D"#660066"><=
br></font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=
=A0 ~my_function() {</font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">=C2=A0 =C2=A0 if (vtable_ !=3D nullptr) {</font></div><div cla=
ss=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 vtable_-=
>destroy_(storage_);</font></div><div class=3D"subprettyprint"><font col=
or=3D"#660066">=C2=A0 =C2=A0 }</font></div><div class=3D"subprettyprint"><f=
ont color=3D"#660066">=C2=A0 }</font></div><div class=3D"subprettyprint"><f=
ont color=3D"#660066"><br></font></div><div class=3D"subprettyprint"><font =
color=3D"#660066">=C2=A0 R operator()(Args... args) {</font></div><div clas=
s=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 vtable_->fun_=
(storage_, std::forward<Args>(args)...);</font></div><div class=3D"su=
bprettyprint"><font color=3D"#660066">=C2=A0 }</font></div><div class=3D"su=
bprettyprint"><font color=3D"#660066"><br></font></div><div class=3D"subpre=
ttyprint"><font color=3D"#660066">=C2=A0 /**</font></div><div class=3D"subp=
rettyprint"><font color=3D"#660066">=C2=A0 =C2=A0* Performing bit-wise swap=
operation is OK!</font></div><div class=3D"subprettyprint"><font color=3D"=
#660066">=C2=A0 =C2=A0*/</font></div><div class=3D"subprettyprint"><font co=
lor=3D"#660066">=C2=A0 void swap(my_function& rhs) {</font></div><div c=
lass=3D"subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 std::swap(sto=
rage_, rhs.storage_);</font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">=C2=A0 =C2=A0 std::swap(vtable_, rhs.vtable_);</font></div><di=
v class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 }</font></div><di=
v class=3D"subprettyprint"><font color=3D"#660066"><br></font></div><div cl=
ass=3D"subprettyprint"><font color=3D"#660066">=C2=A0private:</font></div><=
div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 storage_t stora=
ge_;</font></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=
=A0 const vtable_t<R, Args...>* vtable_;</font></div><div class=3D"su=
bprettyprint"><font color=3D"#660066">};</font></div><div class=3D"subprett=
yprint"><font color=3D"#660066"><br></font></div><div class=3D"subprettypri=
nt"><font color=3D"#660066">int main() {</font></div><div class=3D"subprett=
yprint"><font color=3D"#660066">=C2=A0 my_function<void()> f([] { put=
s("lalala"); });</font></div><div class=3D"subprettyprint"><font =
color=3D"#660066">=C2=A0 f();</font></div><div class=3D"subprettyprint"><fo=
nt color=3D"#660066">=C2=A0 auto g =3D std::move(f);=C2=A0 // Nice!</font><=
/div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 g();</fon=
t></div><div class=3D"subprettyprint"><font color=3D"#660066">=C2=A0 f.swap=
(g);=C2=A0 // Nice!</font></div><div class=3D"subprettyprint"><font color=
=3D"#660066">=C2=A0 f();</font></div><div class=3D"subprettyprint"><font co=
lor=3D"#660066">=C2=A0 return 0;</font></div><div class=3D"subprettyprint">=
<font color=3D"#660066">}</font></div></div></code></div><br>The code works=
fine with latest gcc, clang and msvc.</div><div><br></div><div>Thank you!<=
/div><div><br></div><div>Mingxin Wang<br><br>On Monday, July 2, 2018 at 2:4=
5:20 PM UTC+8, Arthur O'Dwyer wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr">FYI, I just implemented this "check if triv=
ially swappable, and if so, trivially swap" optimization in a branch o=
f SG14's stdext::inplace_function:<div><a href=3D"https://github.com/WG=
21-SG14/SG14/commit/e9bfae8?w=3D1" target=3D"_blank" rel=3D"nofollow" onmou=
sedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgi=
thub.com%2FWG21-SG14%2FSG14%2Fcommit%2Fe9bfae8%3Fw%3D1\x26sa\x3dD\x26sntz\x=
3d1\x26usg\x3dAFQjCNHKy0JuZQc-TT5E4acMUl_MTwao-Q';return true;" onclick=
=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.c=
om%2FWG21-SG14%2FSG14%2Fcommit%2Fe9bfae8%3Fw%3D1\x26sa\x3dD\x26sntz\x3d1\x2=
6usg\x3dAFQjCNHKy0JuZQc-TT5E4acMUl_MTwao-Q';return true;">https://githu=
b.com/WG21-SG14/<wbr>SG14/commit/e9bfae8?w=3D1</a></div><div>And then I rea=
lized that it <i>might</i> be better to stick with the "relocate"=
primitive:<br></div><div><a href=3D"https://github.com/WG21-SG14/SG14/comp=
are/203a411...de43f6e" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"th=
is.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FW=
G21-SG14%2FSG14%2Fcompare%2F203a411...de43f6e\x26sa\x3dD\x26sntz\x3d1\x26us=
g\x3dAFQjCNHpt9XMs34coYVQKlMd6jxHfYWGZQ';return true;" onclick=3D"this.=
href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FWG21=
-SG14%2FSG14%2Fcompare%2F203a411...de43f6e\x26sa\x3dD\x26sntz\x3d1\x26usg\x=
3dAFQjCNHpt9XMs34coYVQKlMd6jxHfYWGZQ';return true;">https://github.com/=
WG21-SG14/<wbr>SG14/compare/203a411...de43f6e</a><br></div><div><br></div><=
div>But if this is <i>only</i> speeding up `swap`, then I still don't r=
eally see the point.=C2=A0 Is anyone motivated to do some kind of benchmark=
to prove that "trivial swap" is a useful operation?</div><div><b=
r></div><div>(Recall that <a href=3D"https://www.youtube.com/watch?v=3DMWBf=
mmg8-Yo&t=3D27m" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'https://www.youtube.com/watch?v\x3dMWBfmmg8-Yo\x26t\x3d27m'=
;;return true;" onclick=3D"this.href=3D'https://www.youtube.com/watch?v=
\x3dMWBfmmg8-Yo\x26t\x3d27m';return true;">I have <i>done</i> the bench=
marks</a> to prove that "trivial relocate" is a useful operation,=
in non-type-erased contexts. What we're looking for here is some speci=
al indication about trivial-swap-in-terms-of-<wbr>trivial-relocate.)</div><=
div><br></div><div>It occurs to me that "trivial swap" might be u=
seful to algorithms such as std::sort, which can be based on swaps. But I&#=
39;m not sure if those algorithms currently work by swapping, or if they wo=
rk by moving (in which case they might be adjusted to work by trivially-rel=
ocating, in the trivially relocatable case).</div><div><br></div><div>=E2=
=80=93Arthur</div></div>
</blockquote></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b6e92c1b-7556-4ca4-8cfa-1618cf5f02b5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b6e92c1b-7556-4ca4-8cfa-1618cf5f02b5=
%40isocpp.org</a>.<br />
------=_Part_10707_257162789.1530527385282--
------=_Part_10706_990475624.1530527385281--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Mon, 2 Jul 2018 10:08:02 -0700
Raw View
--0000000000009048010570073d62
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Mon, Jul 2, 2018 at 3:29 AM, Mingxin Wang <wmx16835vv@163.com> wrote:
> After reading the code, I find the implementation was not exactly
> consistent with what I imagine. I did not mean that the implementation
> should not be compatible with non-trivially-relocatable types, but should
> optimize for trivially-relocatable types. In order to clarify the
> motivation, I made an illustrative example similar to `std::function`,
> which is also the equivalent code expected to be generated with
> `static_proxy<Callable<void>>` defined in the PFA (p0957).
>
> #include <cstdio>
>
> #include <utility>
> #include <type_traits>
>
> /**
> * The definition of is_trivially_relocatable
> * Let's assume that any move constructible type is trivially relocatable
> by
> * default.
> */
> template <class T>
> struct is_trivially_relocatable : std::is_move_constructible<T> {};
>
>
For the purposes of this discussion, I'd greatly prefer/appreciate it if
you'd use a plausible definition, such as
template<class T>
struct is_trivially_relocatable : std::bool_constant<
std::is_trivially_move_constructible_v<T> &&
std::is_trivially_destructible_v<T>
> {};
template<>
struct is_trivially_relocatable<std::string> : std::true_type {};
Using a real definition will make it clear what we're really talking about,
and save a lot of time and confusion. Every time you make up a fake
definition, such as "a type is trivially relocatable iff it is
move-constructible," you make it harder to talk about the actual proposal,
because every question about your proposal ends up having at least two
answers: the fake answer (what happens if we assume "all move-constructible
types are trivially relocatable") and one or more real answers (what
happens if we replace the fake assumption with various real-world
assumptions).
For example, in my "swap" implementation, I found that I needed to make an
executive decision about what to do with types X where
is_trivially_move_constructible_v<X> && is_trivially_destructible_v<X> =
*&&
not is_trivially_assignable_v<X>*
I decided that such types should not be "trivially swapped" by default
(although of course they can opt-in to the trivial swap codepath, the same
way std::string does in my example code above).
>
> template <class T>
> inline constexpr bool USE_SBO =3D
> is_trivially_relocatable_v<T> &&
> sizeof(T) <=3D SBO_SIZE &&
> std::alignment_of_v<T> <=3D std::alignment_of_v<void*>;
>
>
This is similar to what std::function does today, except that today it uses
SBO only when
is_nothrow_relocatable_v<T>
You're going a step further here and saying let's only use SBO for things
where the relocation operation doesn't need to be type-erased at all
(because it's just memcpy).
So you get fewer virtual dispatches, but =E2=80=94 at least on paper =E2=80=
=94 there is a
set of types T that you are "kicking out" of SBO. (Namely, the set of types
which are nothrow-relocatable but not trivially relocatable. For example: a
struct containing an offset_ptr. We very well may not *care* about such
types, there may not *be* many of them in practice, but we should be honest
about what happens to them.)
For what it's worth: inplace_function has no "non-SBO" path, so we can't
use the "kick it out of SBO" approach that you were thinking of, and so I
hadn't really been thinking about it. But you're right, "kick it out of
SBO" is a perfectly valid solution for std::function, std::any, etc.
>
> template <class T>
> static void destroy_impl(storage_t& s) {
> if constexpr (USE_SBO<T>) {
> reinterpret_cast<T*>(s.data_)->~T();
> } else {
> delete static_cast<T*>(s.data_ptr_);
> }
> }
> };
>
> template <class R, class... Args>
> class my_function<R(Args...)> {
> public:
> /**
> * An empty state of the vtable is not designed to keep the code simple
> */
> my_function() : vtable_(nullptr) {}
>
> template <class T>
> my_function(T&& data) : my_function(std::in_place_type<std::decay_t<T>>=
,
> std::forward<T>(data)) {}
>
> template <class T, class... _Args>
> explicit my_function(std::in_place_type_t<T>, _Args&&... args) {
> if constexpr (USE_SBO<T>) {
> new (reinterpret_cast<T*>(storage_.data_))
> T(std::forward<_Args>(args)...);
> } else {
> storage_.data_ptr_ =3D new T(std::forward<_Args>(args)...);
> }
> vtable_ =3D &VTABLE<T, R, Args...>;
> }
>
> /**
> * This is what I want: No dispatch when moving or swapping
> * The code is correct because if the type is NOT trivially relocatable=
,
> it
> * will be stored on the heap, and its pointer is simply trivially
> relocatable.
> */
> my_function(my_function&& rhs) {
> storage_ =3D rhs.storage_;
> vtable_ =3D rhs.vtable_;
> rhs.vtable_ =3D nullptr;
> }
>
I see! This requires that we have the following behavior for
std::function/std::any/etc.:
std::function<void()> f1 =3D foo;
auto f2 =3D std::move(f1);
assert( bool(f1) =3D=3D false );
Right now, libc++ fails the assertion for std::function; libc++ passes the
equivalent assertion for std::any, and libstdc++ passes the assertion in
both cases.
And SG14's stdext::inplace_function fails the assertion too, but I have
just reopened https://github.com/WG21-SG14/SG14/issues/113 to get this
fixed for real.
Speeding up "move-construction" of type-erased types is a bigger deal than
just speeding up "swap"!
By the way, would anyone here be interested in co-authoring a paper on
"is_trivially_relocatable" for San Diego?
Same question in re "is_trivially_comparable /
has_strong_structural_equality" for San Diego.
In both cases I think it's unlikely to get a lot of changes in, but just
getting a standard type-trait (so we can test the trivial relocatability of
lambda types, for example) would be a big win.
Email me offline if so.
=E2=80=93Arthur
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0LvL7GZ38J4WbSwGTrG%3D1tBh2WqzDim07z1%2BKy=
z7To1gA%40mail.gmail.com.
--0000000000009048010570073d62
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Mon, Jul 2, 2018 at 3:29 AM, Mingxin Wang <span dir=3D"=
ltr"><<a href=3D"mailto:wmx16835vv@163.com" target=3D"_blank">wmx16835vv=
@163.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"=
gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr">After reading the code, I fi=
nd the implementation was not=C2=A0exactly consistent with what I imagine. =
I did not mean that the implementation should not be=C2=A0compatible with n=
on-trivially-relocatable types, but should optimize for trivially-relocatab=
le types. In order to clarify the motivation, I made an illustrative exampl=
e similar to `std::function`, which is also the equivalent code expected to=
be generated with `static_proxy<Callable<void>>` defined in th=
e PFA (p0957).<div><br></div><div><div class=3D"gmail-m_-559334351969594280=
5prettyprint" style=3D"background-color:rgb(250,250,250);border:1px solid r=
gb(187,187,187);word-wrap:break-word"><code class=3D"gmail-m_-5593343519695=
942805prettyprint"><div class=3D"gmail-m_-5593343519695942805subprettyprint=
"><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"=
#660066">#include <cstdio></font></div><div class=3D"gmail-m_-5593343=
519695942805subprettyprint"><font color=3D"#660066"><br></font></div><div c=
lass=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066"=
>#include <utility></font></div><div class=3D"gmail-m_-55933435196959=
42805subprettyprint"><font color=3D"#660066">#include <type_traits></=
font></div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font =
color=3D"#660066"><br></font></div><div class=3D"gmail-m_-55933435196959428=
05subprettyprint"><font color=3D"#660066">/**</font></div><div class=3D"gma=
il-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0* Th=
e definition of is_trivially_relocatable</font></div><div class=3D"gmail-m_=
-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0* Let'=
;s assume that any move constructible type is trivially relocatable by</fon=
t></div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font col=
or=3D"#660066">=C2=A0* default.</font></div><div class=3D"gmail-m_-55933435=
19695942805subprettyprint"><font color=3D"#660066">=C2=A0*/</font></div><di=
v class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#6600=
66">template <class T></font></div><div class=3D"gmail-m_-55933435196=
95942805subprettyprint"><font color=3D"#660066">struct is_trivially_relocat=
able : std::is_move_constructible<T> {};</font></div><div class=3D"gm=
ail-m_-5593343519695942805subprettyprint"><font color=3D"#660066"><br></fon=
t></div></div></code></div></div></div></blockquote><div><br></div><div>For=
the purposes of this discussion, I'd greatly prefer/appreciate it if y=
ou'd use a plausible definition, such as</div><div><br></div><div>templ=
ate<class T></div><div>struct is_trivially_relocatable : std::bool_co=
nstant<</div><div>=C2=A0 =C2=A0 std::is_trivially_move_constructible_v&l=
t;T> &&</div><div>=C2=A0 =C2=A0 std::is_trivially_destructible_v=
<T></div><div>> {};<br></div><div>template<></div><div>struc=
t is_trivially_relocatable<std::string> : std::true_type {};</div><di=
v><br></div><div>Using a real definition will make it clear what we're =
really talking about, and save a lot of time and confusion. Every time you =
make up a fake definition, such as "a type is trivially relocatable if=
f it is move-constructible," you make it harder to talk about the actu=
al proposal, because every question about your proposal ends up having at l=
east two answers: the fake answer (what happens if we assume "all move=
-constructible types are trivially relocatable") and one or more real =
answers (what happens if we replace the fake assumption with various real-w=
orld assumptions).</div><div><br></div><div>For example, in my "swap&q=
uot; implementation, I found that I needed to make an executive decision ab=
out what to do with types X where</div><div>=C2=A0 =C2=A0 is_trivially_move=
_constructible_v<X> && is_trivially_destructible_v<X> <=
b>&& not is_trivially_assignable_v<X></b></div><div>I decided=
that such types should not be "trivially swapped" by default (al=
though of course they can opt-in to the trivial swap codepath, the same way=
std::string does in my example code above).</div><div><br></div><div><br><=
/div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-co=
lor:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"=
gmail-m_-5593343519695942805prettyprint" style=3D"background-color:rgb(250,=
250,250);border:1px solid rgb(187,187,187);word-wrap:break-word"><code clas=
s=3D"gmail-m_-5593343519695942805prettyprint"><div class=3D"gmail-m_-559334=
3519695942805subprettyprint"><div class=3D"gmail-m_-5593343519695942805subp=
rettyprint"><font color=3D"#660066"></font></div><div class=3D"gmail-m_-559=
3343519695942805subprettyprint"><br></div><div class=3D"gmail-m_-5593343519=
695942805subprettyprint"><font color=3D"#660066">template <class T></=
font></div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font =
color=3D"#660066">inline constexpr bool USE_SBO =3D</font></div><div class=
=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=
=A0 =C2=A0 is_trivially_relocatable_v<T> &&</font></div><div =
class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066=
">=C2=A0 =C2=A0 sizeof(T) <=3D SBO_SIZE &&</font></div><div clas=
s=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=
=C2=A0 =C2=A0 std::alignment_of_v<T> <=3D std::alignment_of_v<v=
oid*>;</font></div><div class=3D"gmail-m_-5593343519695942805subprettypr=
int"><font color=3D"#660066"><br></font></div></div></code></div></div></di=
v></blockquote><div><br></div><div>This is similar to what std::function do=
es today, except that today it uses SBO only when</div><div>=C2=A0 =C2=A0 i=
s_nothrow_relocatable_v<T></div><div>You're going a step further =
here and saying let's only use SBO for things where the relocation oper=
ation doesn't need to be type-erased at all (because it's just memc=
py).</div><div>So you get fewer virtual dispatches, but =E2=80=94 at least =
on paper =E2=80=94 there is a set of types T that you are "kicking out=
" of SBO. (Namely, the set of types which are nothrow-relocatable but =
not trivially relocatable. For example: a struct containing an offset_ptr. =
We very well may not <i>care</i> about such types, there may not <i>be</i> =
many of them in practice, but we should be honest about what happens to the=
m.)</div><div><br></div><div>For what it's worth: inplace_function has =
no "non-SBO" path, so we can't use the "kick it out of S=
BO" approach that you were thinking of, and so I hadn't really bee=
n thinking about it. But you're right, "kick it out of SBO" i=
s a perfectly valid solution for std::function, std::any, etc.</div><div><b=
r></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left=
-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=
=3D"gmail-m_-5593343519695942805prettyprint" style=3D"background-color:rgb(=
250,250,250);border:1px solid rgb(187,187,187);word-wrap:break-word"><code =
class=3D"gmail-m_-5593343519695942805prettyprint"><div class=3D"gmail-m_-55=
93343519695942805subprettyprint"><div class=3D"gmail-m_-5593343519695942805=
subprettyprint"><font color=3D"#660066"><br></font></div><div class=3D"gmai=
l-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0 temp=
late <class T></font></div><div class=3D"gmail-m_-5593343519695942805=
subprettyprint"><font color=3D"#660066">=C2=A0 static void destroy_impl(sto=
rage_t& s) {</font></div><div class=3D"gmail-m_-5593343519695942805subp=
rettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 if constexpr (USE_SBO<=
T>) {</font></div><div class=3D"gmail-m_-5593343519695942805subprettypri=
nt"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 reinterpret_cast<T*>=
(s.data_)-<wbr>>~T();</font></div><div class=3D"gmail-m_-559334351969594=
2805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 } else {</font></=
div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=
=3D"#660066">=C2=A0 =C2=A0 =C2=A0 delete static_cast<T*>(s.data_ptr_)=
;</font></div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><fo=
nt color=3D"#660066">=C2=A0 =C2=A0 }</font></div><div class=3D"gmail-m_-559=
3343519695942805subprettyprint"><font color=3D"#660066">=C2=A0 }</font></di=
v><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"=
#660066">};</font></div><div class=3D"gmail-m_-5593343519695942805subpretty=
print"><br></div><div class=3D"gmail-m_-5593343519695942805subprettyprint">=
<font color=3D"#660066">template <class R, class... Args></font></div=
><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#=
660066">class my_function<R(Args...)> {</font></div><div class=3D"gma=
il-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0publ=
ic:</font></div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><=
font color=3D"#660066">=C2=A0 /**</font></div><div class=3D"gmail-m_-559334=
3519695942805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0* An empt=
y state of the vtable is not designed to keep the code simple</font></div><=
div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#66=
0066">=C2=A0 =C2=A0*/</font></div><div class=3D"gmail-m_-559334351969594280=
5subprettyprint"><font color=3D"#660066">=C2=A0 my_function() : vtable_(nul=
lptr) {}</font></div><div class=3D"gmail-m_-5593343519695942805subprettypri=
nt"><font color=3D"#660066"><br></font></div><div class=3D"gmail-m_-5593343=
519695942805subprettyprint"><font color=3D"#660066">=C2=A0 template <cla=
ss T></font></div><div class=3D"gmail-m_-5593343519695942805subprettypri=
nt"><font color=3D"#660066">=C2=A0 my_function(T&& data) : my_funct=
ion(std::in_place_<wbr>type<std::decay_t<T>>,</font></div><div =
class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066=
">=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 =C2=A0 =C2=A0 =C2=A0 std::forward<=
;T>(data)) {}</font></div><div class=3D"gmail-m_-5593343519695942805subp=
rettyprint"><font color=3D"#660066"><br></font></div><div class=3D"gmail-m_=
-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0 template=
<class T, class... _Args></font></div><div class=3D"gmail-m_-5593343=
519695942805subprettyprint"><font color=3D"#660066">=C2=A0 explicit my_func=
tion(std::in_place_<wbr>type_t<T>, _Args&&... args) {</font><=
/div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=
=3D"#660066">=C2=A0 =C2=A0 if constexpr (USE_SBO<T>) {</font></div><d=
iv class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660=
066">=C2=A0 =C2=A0 =C2=A0 new (reinterpret_cast<T*>(storage_<wbr>.dat=
a_)) T(std::forward<_Args>(args)...<wbr>);</font></div><div class=3D"=
gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0 =
=C2=A0 } else {</font></div><div class=3D"gmail-m_-5593343519695942805subpr=
ettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 =C2=A0 storage_.data_ptr_ =
=3D new T(std::forward<_Args>(args)...<wbr>);</font></div><div class=
=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=
=A0 =C2=A0 }</font></div><div class=3D"gmail-m_-5593343519695942805subprett=
yprint"><font color=3D"#660066">=C2=A0 =C2=A0 vtable_ =3D &VTABLE<T,=
R, Args...>;</font></div><div class=3D"gmail-m_-5593343519695942805subp=
rettyprint"><font color=3D"#660066">=C2=A0 }</font></div><div class=3D"gmai=
l-m_-5593343519695942805subprettyprint"><font color=3D"#660066"><br></font>=
</div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=
=3D"#660066">=C2=A0 /**</font></div><div class=3D"gmail-m_-5593343519695942=
805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0* This is what I wa=
nt: No dispatch when moving or swapping</font></div><div class=3D"gmail-m_-=
5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0* T=
he code is correct because if the type is NOT trivially relocatable, it</fo=
nt></div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font co=
lor=3D"#660066">=C2=A0 =C2=A0* will be stored on the heap, and its pointer =
is simply trivially relocatable.</font></div><div class=3D"gmail-m_-5593343=
519695942805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0*/</font><=
/div><div class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=
=3D"#660066">=C2=A0 my_function(my_function&& rhs) {</font></div><d=
iv class=3D"gmail-m_-5593343519695942805subprettyprint"><font color=3D"#660=
066">=C2=A0 =C2=A0 storage_ =3D rhs.storage_;</font></div><div class=3D"gma=
il-m_-5593343519695942805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=
=A0 vtable_ =3D rhs.vtable_;</font></div><div class=3D"gmail-m_-55933435196=
95942805subprettyprint"><font color=3D"#660066">=C2=A0 =C2=A0 rhs.vtable_ =
=3D nullptr;</font></div><div class=3D"gmail-m_-5593343519695942805subprett=
yprint"><font color=3D"#660066">=C2=A0 }</font></div></div></code></div></d=
iv></div></blockquote><div><br></div><div>I see!=C2=A0 This requires that w=
e have the following behavior for std::function/std::any/etc.:</div><div><b=
r></div><div><div>=C2=A0 =C2=A0 std::function<void()> f1 =3D foo;</di=
v><div>=C2=A0 =C2=A0 auto f2 =3D std::move(f1);</div><div>=C2=A0 =C2=A0 ass=
ert( bool(f1) =3D=3D false );</div></div><div><br></div><div>Right now, lib=
c++ fails the assertion for std::function; libc++ passes the equivalent ass=
ertion for std::any, and libstdc++ passes the assertion in both cases.</div=
><div>And SG14's stdext::inplace_function fails the assertion too, but =
I have just reopened=C2=A0<a href=3D"https://github.com/WG21-SG14/SG14/issu=
es/113">https://github.com/WG21-SG14/SG14/issues/113</a> to get this fixed =
for real.</div><div><br></div><div>Speeding up "move-construction"=
; of type-erased types is a bigger deal than just speeding up "swap&qu=
ot;!</div><div><br></div><div>By the way, would anyone here be interested i=
n co-authoring a paper on "is_trivially_relocatable" for San Dieg=
o?</div><div>Same question in re "is_trivially_comparable / has_strong=
_structural_equality" for San Diego.</div><div>In both cases I think i=
t's unlikely to get a lot of changes in, but just getting a standard ty=
pe-trait (so we can test the trivial relocatability of lambda types, for ex=
ample) would be a big win.</div><div>Email me offline if so.</div><div><br>=
</div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0LvL7GZ38J4WbSwGTrG%3D1tBh2WqzD=
im07z1%2BKyz7To1gA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0LvL7GZ=
38J4WbSwGTrG%3D1tBh2WqzDim07z1%2BKyz7To1gA%40mail.gmail.com</a>.<br />
--0000000000009048010570073d62--
.