Topic: Relocation as a solution for the valueless variant problem?
Author: isocppgroup@denisbider.com
Date: Tue, 5 Apr 2016 16:58:18 -0700 (PDT)
Raw View
------=_Part_1174_267811751.1459900698320
Content-Type: multipart/alternative;
boundary="----=_Part_1175_2052105130.1459900698320"
------=_Part_1175_2052105130.1459900698320
Content-Type: text/plain; charset=UTF-8
A proposal has recently been floated:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html
.... which proposes pilfering as a solution to the valueless variant problem.
Please correct me if I'm wrong - my understanding of the valueless variant
problem is that it arises if a move constructor throws during assignment
and emplacement, such as this:
std::variant<X, Y> a = X();
std::variant<X, Y> b = Y();
try { b = std::move(a); } // bad_alloc here
catch (std::bad_alloc) {}
In this case, variant's assignment operator has to do something like this:
b.y.~Y();
new (&b.x) X(std::move(a.x));
To avoid a valueless result in case of exception, one's first thought might
be to move first into a temporary:
X temp { std::move(a.x) };
b.y.~Y();
new (&b.x) X(std::move(temp.x);
Unfortunately, this does not gain anything. Now the second move constructor
may throw, resulting in the same situation.
However!
If C++ implemented relocation, as described in this proposal P0023:
http://denisbider.com/Relocator.pdf
Then the solution involving a temporary would work:
std::aligned_storage_t<sizeof(X), alignof(X)> tempData;
X* temp = new (tempData) { std::move(a.x) };
b.y.~Y();
new (&b.x) >>X(*temp);
This would now be exception-safe:
- without requiring pilfering;
- and without a potentially, but almost never, valueless variant.
Food for thought?
I believe the relocation proposal has so far not progressed for, at least,
these two reasons:
(1) Proposals require champions to travel to meetings to represent them.
(2) I am not willing to travel for this proposal, because I think the C++
committee should just do the right thing, independent of who travels to a
meeting.
The language should consider ideas based on their merit - not conditional
on the appearance of valiant knights who will cross swamps and deserts, to
rescue ideas from a castle. :-)
--
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/b4feb52d-4cd0-475f-9f3d-6694564bc1b0%40isocpp.org.
------=_Part_1175_2052105130.1459900698320
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>A proposal has recently been floated:</div><div><br><=
/div><div><a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/201=
6/p0308r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p03=
08r0.html</a></div><div><br></div><div>... which proposes pilfering as a so=
lution to the valueless variant problem.</div><div><br></div><div>Please co=
rrect me if I'm wrong - my understanding of the valueless variant probl=
em is that it arises if a move constructor throws during assignment and emp=
lacement, such as this:</div><div><br></div><div><pre style=3D"background: =
rgb(246, 248, 255); color: rgb(0, 0, 32);"> <span style=3D"color: rgb(0, 1=
02, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">::</span>vari=
ant<span style=3D"color: rgb(64, 96, 128);"><</span>X<span style=3D"colo=
r: rgb(48, 128, 128);">,</span> Y<span style=3D"color: rgb(64, 96, 128);">&=
gt;</span> a <span style=3D"color: rgb(48, 128, 128);">=3D</span> X<span st=
yle=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48, 128=
, 128);">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(0, 102, 238);">std</span><span style=3D"color: =
rgb(64, 96, 128);">::</span>variant<span style=3D"color: rgb(64, 96, 128);"=
><</span>X<span style=3D"color: rgb(48, 128, 128);">,</span> Y<span styl=
e=3D"color: rgb(64, 96, 128);">></span> b <span style=3D"color: rgb(48, =
128, 128);">=3D</span> Y<span style=3D"color: rgb(48, 128, 128);">(</span><=
span style=3D"color: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(=
64, 96, 128);">;</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">try</span> <sp=
an style=3D"color: rgb(64, 96, 128);">{</span> b <span style=3D"color: rgb(=
48, 128, 128);">=3D</span> <span style=3D"color: rgb(0, 102, 238);">std</sp=
an><span style=3D"color: rgb(64, 96, 128);">::</span><span style=3D"color: =
rgb(0, 48, 96);">move</span><span style=3D"color: rgb(48, 128, 128);">(</sp=
an>a<span style=3D"color: rgb(48, 128, 128);">)</span><span style=3D"color:=
rgb(64, 96, 128);">;</span> <span style=3D"color: rgb(64, 96, 128);">}</sp=
an> <span style=3D"color: rgb(89, 89, 121);">// bad_alloc here</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">catch</span> <=
span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(=
0, 102, 238);">std</span><span style=3D"color: rgb(64, 96, 128);">::</span>=
<span style=3D"color: rgb(0, 48, 96);">bad_alloc</span><span style=3D"color=
: rgb(48, 128, 128);">)</span> <span style=3D"color: rgb(64, 96, 128);">{</=
span><span style=3D"color: rgb(64, 96, 128);">}</span>
</pre></div><div><br></div><div>In this case, variant's assignment oper=
ator has to do something like this:</div><div><br></div><div><pre style=3D"=
background: rgb(246, 248, 255); color: rgb(0, 0, 32);"> b<span style=3D"co=
lor: rgb(48, 128, 128);">.</span>y<span style=3D"color: rgb(48, 128, 128);"=
>.</span><span style=3D"color: rgb(48, 128, 128);">~</span>Y<span style=3D"=
color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48, 128, 128);=
">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">new</span> <sp=
an style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48=
, 128, 128);">&</span>b<span style=3D"color: rgb(48, 128, 128);">.</spa=
n>x<span style=3D"color: rgb(48, 128, 128);">)</span> X<span style=3D"color=
: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(0, 102, 238);">std<=
/span><span style=3D"color: rgb(64, 96, 128);">::</span><span style=3D"colo=
r: rgb(0, 48, 96);">move</span><span style=3D"color: rgb(48, 128, 128);">(<=
/span>a<span style=3D"color: rgb(48, 128, 128);">.</span>x<span style=3D"co=
lor: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(48, 128, 128);">=
)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
</pre></div><div><br></div><div>To avoid a valueless result in case of exce=
ption, one's first thought might be to move first into a temporary:</di=
v><div><br></div><div><pre style=3D"background: rgb(246, 248, 255); color: =
rgb(0, 0, 32);"> X temp <span style=3D"color: rgb(64, 96, 128);">{</span> =
<span style=3D"color: rgb(0, 102, 238);">std</span><span style=3D"color: rg=
b(64, 96, 128);">::</span><span style=3D"color: rgb(0, 48, 96);">move</span=
><span style=3D"color: rgb(48, 128, 128);">(</span>a<span style=3D"color: r=
gb(48, 128, 128);">.</span>x<span style=3D"color: rgb(48, 128, 128);">)</sp=
an> <span style=3D"color: rgb(64, 96, 128);">}</span><span style=3D"color: =
rgb(64, 96, 128);">;</span>
b<span style=3D"color: rgb(48, 128, 128);">.</span>y<span style=3D"color:=
rgb(48, 128, 128);">.</span><span style=3D"color: rgb(48, 128, 128);">~</s=
pan>Y<span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color=
: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(64, 96, 128);">;</s=
pan>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">new</span> <sp=
an style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48=
, 128, 128);">&</span>b<span style=3D"color: rgb(48, 128, 128);">.</spa=
n>x<span style=3D"color: rgb(48, 128, 128);">)</span> X<span style=3D"color=
: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(0, 102, 238);">std<=
/span><span style=3D"color: rgb(64, 96, 128);">::</span><span style=3D"colo=
r: rgb(0, 48, 96);">move</span><span style=3D"color: rgb(48, 128, 128);">(<=
/span>temp<span style=3D"color: rgb(48, 128, 128);">.</span>x<span style=3D=
"color: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(64, 96, 128);=
">;</span>
</pre></div><div><br></div><div>Unfortunately, this does not gain anything.=
Now the second move constructor may throw, resulting in the same situation=
..</div><div><br></div><div>However!</div><div><br></div><div>If C++ impleme=
nted relocation, as described in this proposal P0023:</div><div><br></div><=
div><a href=3D"http://denisbider.com/Relocator.pdf">http://denisbider.com/R=
elocator.pdf</a></div><div><br></div><div>Then the solution involving a tem=
porary would work:</div><div><br></div><div><pre style=3D"background: rgb(2=
46, 248, 255); color: rgb(0, 0, 32);"> <span style=3D"color: rgb(0, 102, 2=
38);">std</span><span style=3D"color: rgb(64, 96, 128);">::</span>aligned_s=
torage_t<span style=3D"color: rgb(64, 96, 128);"><</span><span style=3D"=
color: rgb(32, 0, 128); font-weight: bold;">sizeof</span><span style=3D"col=
or: rgb(48, 128, 128);">(</span>X<span style=3D"color: rgb(48, 128, 128);">=
)</span><span style=3D"color: rgb(48, 128, 128);">,</span> alignof<span sty=
le=3D"color: rgb(48, 128, 128);">(</span>X<span style=3D"color: rgb(48, 128=
, 128);">)</span><span style=3D"color: rgb(64, 96, 128);">></span> tempD=
ata<span style=3D"color: rgb(64, 96, 128);">;</span>
X<span style=3D"color: rgb(48, 128, 128);">*</span> temp <span style=3D"c=
olor: rgb(48, 128, 128);">=3D</span> <span style=3D"color: rgb(32, 0, 128);=
font-weight: bold;">new</span> <span style=3D"color: rgb(48, 128, 128);">(=
</span>tempData<span style=3D"color: rgb(48, 128, 128);">)</span> <span sty=
le=3D"color: rgb(64, 96, 128);">{</span> <span style=3D"color: rgb(0, 102, =
238);">std</span><span style=3D"color: rgb(64, 96, 128);">::</span><span st=
yle=3D"color: rgb(0, 48, 96);">move</span><span style=3D"color: rgb(48, 128=
, 128);">(</span>a<span style=3D"color: rgb(48, 128, 128);">.</span>x<span =
style=3D"color: rgb(48, 128, 128);">)</span> <span style=3D"color: rgb(64, =
96, 128);">}</span><span style=3D"color: rgb(64, 96, 128);">;</span>
b<span style=3D"color: rgb(48, 128, 128);">.</span>y<span style=3D"color:=
rgb(48, 128, 128);">.</span><span style=3D"color: rgb(48, 128, 128);">~</s=
pan>Y<span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color=
: rgb(48, 128, 128);">)</span><span style=3D"color: rgb(64, 96, 128);">;</s=
pan>
<span style=3D"color: rgb(32, 0, 128); font-weight: bold;">new</span> <sp=
an style=3D"color: rgb(48, 128, 128);">(</span><span style=3D"color: rgb(48=
, 128, 128);">&</span>b<span style=3D"color: rgb(48, 128, 128);">.</spa=
n>x<span style=3D"color: rgb(48, 128, 128);">)</span> <span style=3D"color:=
rgb(48, 128, 128);">></span><span style=3D"color: rgb(48, 128, 128);">&=
gt;</span>X<span style=3D"color: rgb(48, 128, 128);">(</span><span style=3D=
"color: rgb(48, 128, 128);">*</span>temp<span style=3D"color: rgb(48, 128, =
128);">)</span><span style=3D"color: rgb(64, 96, 128);">;</span>
</pre></div><div><br></div><div>This would now be exception-safe:</div><div=
><br></div><div>- without requiring pilfering;</div><div>- and without a=C2=
=A0potentially, but almost never, valueless variant.</div><div><div><div><d=
iv><br></div><div>Food for thought?</div><div><br></div></div></div></div><=
div>I believe the relocation proposal has so far not progressed for, at lea=
st, these two reasons:</div><div><br></div><div>(1)=C2=A0Proposals require =
champions to travel to meetings=C2=A0to represent them.</div><div>(2)=C2=A0=
I am not willing to travel for this proposal, because I think the C++ commi=
ttee should just do the right thing, independent of who travels to a meetin=
g.</div><div><br></div><div>The language should=C2=A0consider ideas based=
=C2=A0on their merit -=C2=A0not conditional on the appearance of valiant kn=
ights who=C2=A0will cross swamps and deserts, to rescue=C2=A0ideas=C2=A0fro=
m a castle. :-)</div><div><br></div><div><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/b4feb52d-4cd0-475f-9f3d-6694564bc1b0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b4feb52d-4cd0-475f-9f3d-6694564bc1b0=
%40isocpp.org</a>.<br />
------=_Part_1175_2052105130.1459900698320--
------=_Part_1174_267811751.1459900698320--
.