Topic: Does guaranteed elision breaks bit_cast?


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 6 Dec 2017 11:43:31 -0800 (PST)
Raw View
------=_Part_577_139033694.1512589411209
Content-Type: multipart/alternative;
 boundary="----=_Part_578_1276454921.1512589411209"

------=_Part_578_1276454921.1512589411209
Content-Type: text/plain; charset="UTF-8"

The new `bit_cast` feature voted into C++20 allows you to do this:

int i = ...;
float j = bit_cast<float>(i);

Assuming the two types have the same size.

The concern is what happens with this:

int i = ...;
float *f = new(&i) auto(bit_cast<float>(i));

Well, the rules of guaranteed elision require that the prvalue returned by
`bit_cast` directly initializes the object. And that object's storage is
the same as the parameter passed to `bit_cast`.

So... how exactly does that work? Is this just something that is just for
implementers to worry about? Or should there be standard wording to
explicitly forbid this?

--
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/383622f1-4c62-4af6-b684-c3d0fdcd3b9c%40isocpp.org.

------=_Part_578_1276454921.1512589411209
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>The new `bit_cast` feature voted into C++20 allows yo=
u to do this:</div><div><br></div><div class=3D"prettyprint" style=3D"borde=
r: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: r=
gb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprin=
t"><span class=3D"styled-by-prettify" style=3D"color: #008;">int</span><spa=
n class=3D"styled-by-prettify" style=3D"color: #000;"> i </span><span class=
=3D"styled-by-prettify" style=3D"color: #660;">=3D</span><span class=3D"sty=
led-by-prettify" style=3D"color: #000;"> </span><span class=3D"styled-by-pr=
ettify" style=3D"color: #660;">...;</span><span class=3D"styled-by-prettify=
" style=3D"color: #000;"><br></span><span class=3D"styled-by-prettify" styl=
e=3D"color: #008;">float</span><span class=3D"styled-by-prettify" style=3D"=
color: #000;"> j </span><span class=3D"styled-by-prettify" style=3D"color: =
#660;">=3D</span><span class=3D"styled-by-prettify" style=3D"color: #000;">=
 bit_cast</span><span class=3D"styled-by-prettify" style=3D"color: #080;">&=
lt;float&gt;</span><span class=3D"styled-by-prettify" style=3D"color: #660;=
">(</span><span class=3D"styled-by-prettify" style=3D"color: #000;">i</span=
><span class=3D"styled-by-prettify" style=3D"color: #660;">);</span></div><=
/code></div><div><br></div><div>Assuming the two types have the same size.<=
/div><div><br></div><div>The concern is what happens with this:</div><div><=
br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187=
, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"><code=
 class=3D"prettyprint"><div class=3D"subprettyprint"><span class=3D"styled-=
by-prettify" style=3D"color: #008;">int</span><span class=3D"styled-by-pret=
tify" style=3D"color: #000;"> i </span><span class=3D"styled-by-prettify" s=
tyle=3D"color: #660;">=3D</span><span class=3D"styled-by-prettify" style=3D=
"color: #000;"> </span><span class=3D"styled-by-prettify" style=3D"color: #=
660;">...;</span><span class=3D"styled-by-prettify" style=3D"color: #000;">=
<br></span><span class=3D"styled-by-prettify" style=3D"color: #008;">float<=
/span><span class=3D"styled-by-prettify" style=3D"color: #000;"> </span><sp=
an class=3D"styled-by-prettify" style=3D"color: #660;">*</span><span class=
=3D"styled-by-prettify" style=3D"color: #000;">f </span><span class=3D"styl=
ed-by-prettify" style=3D"color: #660;">=3D</span><span class=3D"styled-by-p=
rettify" style=3D"color: #000;"> </span><span class=3D"styled-by-prettify" =
style=3D"color: #008;">new</span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">(&amp;</span><span class=3D"styled-by-prettify" style=3D"=
color: #000;">i</span><span class=3D"styled-by-prettify" style=3D"color: #6=
60;">)</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> </s=
pan><span class=3D"styled-by-prettify" style=3D"color: #008;">auto</span><s=
pan class=3D"styled-by-prettify" style=3D"color: #660;">(</span><span class=
=3D"styled-by-prettify" style=3D"color: #000;">bit_cast</span><span class=
=3D"styled-by-prettify" style=3D"color: #080;">&lt;float&gt;</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #660;">(</span><span class=3D"st=
yled-by-prettify" style=3D"color: #000;">i</span><span class=3D"styled-by-p=
rettify" style=3D"color: #660;">));</span></div></code></div><div><br></div=
><div>Well, the rules of guaranteed elision require that the prvalue return=
ed by `bit_cast` directly initializes the object. And that object&#39;s sto=
rage is the same as the parameter passed to `bit_cast`.</div><div><br></div=
><div>So... how exactly does that work? Is this just something that is just=
 for implementers to worry about? Or should there be standard wording to ex=
plicitly forbid this?</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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/383622f1-4c62-4af6-b684-c3d0fdcd3b9c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/383622f1-4c62-4af6-b684-c3d0fdcd3b9c=
%40isocpp.org</a>.<br />

------=_Part_578_1276454921.1512589411209--

------=_Part_577_139033694.1512589411209--

.


Author: Myriachan <myriachan@gmail.com>
Date: Wed, 6 Dec 2017 12:52:58 -0800 (PST)
Raw View
------=_Part_864_841127964.1512593578845
Content-Type: multipart/alternative;
 boundary="----=_Part_865_2029533041.1512593578845"

------=_Part_865_2029533041.1512593578845
Content-Type: text/plain; charset="UTF-8"

On Wednesday, December 6, 2017 at 11:43:31 AM UTC-8, Nicol Bolas wrote:
>
> The new `bit_cast` feature voted into C++20 allows you to do this:
>
> int i = ...;
> float j = bit_cast<float>(i);
>
> Assuming the two types have the same size.
>
> The concern is what happens with this:
>
> int i = ...;
> float *f = new(&i) auto(bit_cast<float>(i));
>
> Well, the rules of guaranteed elision require that the prvalue returned by
> `bit_cast` directly initializes the object. And that object's storage is
> the same as the parameter passed to `bit_cast`.
>
> So... how exactly does that work? Is this just something that is just for
> implementers to worry about? Or should there be standard wording to
> explicitly forbid this?
>


As I understand it, eliding copy constructors is generally implemented by
adding an invisible reference parameter to the target, so we could imagine
that the above code gets translated into this C code:

float *bit_cast_float(const int *i, float *return_value)
{
    memmove(return_value, i, sizeof(float));
    return return_value;
}

int i = ...;
float *f = bit_cast_float(&i, (float *) &i);


Why would this break anything?

Melissa

--
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/c6bd73c7-ae4a-4e24-b33e-90257aae9702%40isocpp.org.

------=_Part_865_2029533041.1512593578845
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, December 6, 2017 at 11:43:31 AM UTC-8, Nicol=
 Bolas 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">=
<div>The new `bit_cast` feature voted into C++20 allows you to do this:</di=
v><div><br></div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:=
break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"col=
or:#008">int</span><span style=3D"color:#000"> i </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">...;</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#008">float</span><span style=3D"color:#000"> j </span><span style=3D"color=
:#660">=3D</span><span style=3D"color:#000"> bit_cast</span><span style=3D"=
color:#080">&lt;float&gt;</span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#000">i</span><span style=3D"color:#660">);</span></div></code=
></div><div><br></div><div>Assuming the two types have the same size.</div>=
<div><br></div><div>The concern is what happens with this:</div><div><br></=
div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;ba=
ckground-color:rgb(250,250,250)"><code><div><span style=3D"color:#008">int<=
/span><span style=3D"color:#000"> i </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">...;</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#008">float</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">*</span>=
<span style=3D"color:#000">f </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">new</span><span=
 style=3D"color:#660">(&amp;</span><span style=3D"color:#000">i</span><span=
 style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">auto</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">bit_cast</span><span style=3D"color:#080">&lt;float&gt;</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">i</span><s=
pan style=3D"color:#660">));</span></div></code></div><div><br></div><div>W=
ell, the rules of guaranteed elision require that the prvalue returned by `=
bit_cast` directly initializes the object. And that object&#39;s storage is=
 the same as the parameter passed to `bit_cast`.</div><div><br></div><div>S=
o... how exactly does that work? Is this just something that is just for im=
plementers to worry about? Or should there be standard wording to explicitl=
y forbid this?</div></div></blockquote><div><br></div><div><br></div><div>A=
s I understand it, eliding copy constructors is generally implemented by ad=
ding an invisible reference parameter to the target, so we could imagine th=
at the above code gets translated into this C code:</div><div><br></div><di=
v><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187=
, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: break-w=
ord;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpr=
ettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">float<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">bit_cast_float</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">float</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">return_value</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 memmove</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">return_value</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> i</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: #008;" class=3D"styled-by-prettify">float</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">));</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> return_value</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> i </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">...;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">float</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">f </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> bit_cast_float</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(&amp;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">i</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">float</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;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">i</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">);</span></div></code></div><br></div><div></div><br>Why would this bre=
ak anything?<br><br>Melissa<br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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/c6bd73c7-ae4a-4e24-b33e-90257aae9702%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c6bd73c7-ae4a-4e24-b33e-90257aae9702=
%40isocpp.org</a>.<br />

------=_Part_865_2029533041.1512593578845--

------=_Part_864_841127964.1512593578845--

.


Author: Richard Smith <richard@metafoo.co.uk>
Date: Wed, 6 Dec 2017 13:20:38 -0800
Raw View
--001a113cd6641d2665055fb287da
Content-Type: text/plain; charset="UTF-8"

On 6 December 2017 at 11:43, Nicol Bolas <jmckesson@gmail.com> wrote:

> The new `bit_cast` feature voted into C++20 allows you to do this:
>
> int i = ...;
> float j = bit_cast<float>(i);
>
> Assuming the two types have the same size.
>
> The concern is what happens with this:
>
> int i = ...;
> float *f = new(&i) auto(bit_cast<float>(i));
>
> Well, the rules of guaranteed elision require that the prvalue returned by
> `bit_cast` directly initializes the object. And that object's storage is
> the same as the parameter passed to `bit_cast`.
>
> So... how exactly does that work? Is this just something that is just for
> implementers to worry about? Or should there be standard wording to
> explicitly forbid this?
>

Per [expr.new]p19, the invocation of the allocation function is sequenced
before the evaluation of the initializer. So first we run the placement new
operator. Once it returns, we begin to reuse its storage to hold a
different object (the float object we're initializing), so by
[basic.life]/1.3, the lifetime of the int object ends, and by
[basic.life]/4, properties ascribed to that object (such as the object
holding a particular value) cease to apply. The bit_cast happens too late.

Guaranteed copy elision might make it a bit more obvious that this could be
a problem, but the lifetime and sequencing rules result in this being UB
regardless of guaranteed copy elision. Here's another example where it's
perhaps slightly more obvious that the code is broken:

struct X { int a, b; };
double d;
X *p = new (&d) X { 0, d };

Note that an implementation is permitted to store 0 to the first half of d
before considering initializing the second half (and in particular, loading
from d). This example has never performed a copy of an X object, and it
wouldn't matter if it did -- the lifetime of d ends the moment that
evaluation of the initializer begins.

--
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/CAOfiQqm-W21i8kdS62gx-XwhXPcsEgkfhr6esE4geGMNzT3Dhg%40mail.gmail.com.

--001a113cd6641d2665055fb287da
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On 6=
 December 2017 at 11:43, Nicol Bolas <span dir=3D"ltr">&lt;<a href=3D"mailt=
o:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&gt;</span>=
 wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The new `bi=
t_cast` feature voted into C++20 allows you to do this:</div><div><br></div=
><div class=3D"m_-6501156243865073061prettyprint" style=3D"border:1px solid=
 rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><=
code class=3D"m_-6501156243865073061prettyprint"><div class=3D"m_-650115624=
3865073061subprettyprint"><span class=3D"m_-6501156243865073061styled-by-pr=
ettify" style=3D"color:#008">int</span><span class=3D"m_-650115624386507306=
1styled-by-prettify" style=3D"color:#000"> i </span><span class=3D"m_-65011=
56243865073061styled-by-prettify" style=3D"color:#660">=3D</span><span clas=
s=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#000"> </span=
><span class=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#6=
60">...;</span><span class=3D"m_-6501156243865073061styled-by-prettify" sty=
le=3D"color:#000"><br></span><span class=3D"m_-6501156243865073061styled-by=
-prettify" style=3D"color:#008">float</span><span class=3D"m_-6501156243865=
073061styled-by-prettify" style=3D"color:#000"> j </span><span class=3D"m_-=
6501156243865073061styled-by-prettify" style=3D"color:#660">=3D</span><span=
 class=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#000"> b=
it_cast</span><span class=3D"m_-6501156243865073061styled-by-prettify" styl=
e=3D"color:#080">&lt;float&gt;</span><span class=3D"m_-6501156243865073061s=
tyled-by-prettify" style=3D"color:#660">(</span><span class=3D"m_-650115624=
3865073061styled-by-prettify" style=3D"color:#000">i</span><span class=3D"m=
_-6501156243865073061styled-by-prettify" style=3D"color:#660">);</span></di=
v></code></div><div><br></div><div>Assuming the two types have the same siz=
e.</div><div><br></div><div>The concern is what happens with this:</div><di=
v><br></div><div class=3D"m_-6501156243865073061prettyprint" style=3D"borde=
r:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,=
250,250)"><code class=3D"m_-6501156243865073061prettyprint"><div class=3D"m=
_-6501156243865073061subprettyprint"><span class=3D"m_-6501156243865073061s=
tyled-by-prettify" style=3D"color:#008">int</span><span class=3D"m_-6501156=
243865073061styled-by-prettify" style=3D"color:#000"> i </span><span class=
=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#660">=3D</spa=
n><span class=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#=
000"> </span><span class=3D"m_-6501156243865073061styled-by-prettify" style=
=3D"color:#660">...;</span><span class=3D"m_-6501156243865073061styled-by-p=
rettify" style=3D"color:#000"><br></span><span class=3D"m_-6501156243865073=
061styled-by-prettify" style=3D"color:#008">float</span><span class=3D"m_-6=
501156243865073061styled-by-prettify" style=3D"color:#000"> </span><span cl=
ass=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#660">*</sp=
an><span class=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:=
#000">f </span><span class=3D"m_-6501156243865073061styled-by-prettify" sty=
le=3D"color:#660">=3D</span><span class=3D"m_-6501156243865073061styled-by-=
prettify" style=3D"color:#000"> </span><span class=3D"m_-650115624386507306=
1styled-by-prettify" style=3D"color:#008">new</span><span class=3D"m_-65011=
56243865073061styled-by-prettify" style=3D"color:#660">(&amp;</span><span c=
lass=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#000">i</s=
pan><span class=3D"m_-6501156243865073061styled-by-prettify" style=3D"color=
:#660">)</span><span class=3D"m_-6501156243865073061styled-by-prettify" sty=
le=3D"color:#000"> </span><span class=3D"m_-6501156243865073061styled-by-pr=
ettify" style=3D"color:#008">auto</span><span class=3D"m_-65011562438650730=
61styled-by-prettify" style=3D"color:#660">(</span><span class=3D"m_-650115=
6243865073061styled-by-prettify" style=3D"color:#000">bit_cast</span><span =
class=3D"m_-6501156243865073061styled-by-prettify" style=3D"color:#080">&lt=
;float&gt;</span><span class=3D"m_-6501156243865073061styled-by-prettify" s=
tyle=3D"color:#660">(</span><span class=3D"m_-6501156243865073061styled-by-=
prettify" style=3D"color:#000">i</span><span class=3D"m_-650115624386507306=
1styled-by-prettify" style=3D"color:#660">));</span></div></code></div><div=
><br></div><div>Well, the rules of guaranteed elision require that the prva=
lue returned by `bit_cast` directly initializes the object. And that object=
&#39;s storage is the same as the parameter passed to `bit_cast`.</div><div=
><br></div><div>So... how exactly does that work? Is this just something th=
at is just for implementers to worry about? Or should there be standard wor=
ding to explicitly forbid this?</div></div></blockquote><div><br></div><div=
>Per [expr.new]p19, the invocation of the allocation function is sequenced =
before the evaluation of the initializer. So first we run the placement new=
 operator. Once it returns, we begin to reuse its storage to hold a differe=
nt object (the float object we&#39;re initializing), so by [basic.life]/1.3=
, the lifetime of the int object ends, and by [basic.life]/4, properties as=
cribed to that object (such as the object holding a particular value) cease=
 to apply. The bit_cast happens too late.</div><div><br></div><div>Guarante=
ed copy elision might make it a bit more obvious that this could be a probl=
em, but the lifetime and sequencing rules result in this being UB regardles=
s of guaranteed copy elision. Here&#39;s another example where it&#39;s per=
haps slightly more obvious that the code is broken:</div><div><br></div><di=
v>struct X { int a, b; };</div><div>double d;</div><div>X *p =3D new (&amp;=
d) X { 0, d };</div><div><br></div><div>Note that an implementation is perm=
itted to store 0 to the first half of d before considering initializing the=
 second half (and in particular, loading from d). This example has never pe=
rformed a copy of an X object, and it wouldn&#39;t matter if it did -- the =
lifetime of d ends the moment that evaluation of the initializer begins.</d=
iv></div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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/CAOfiQqm-W21i8kdS62gx-XwhXPcsEgkfhr6e=
sE4geGMNzT3Dhg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOfiQqm-W21i8kdS=
62gx-XwhXPcsEgkfhr6esE4geGMNzT3Dhg%40mail.gmail.com</a>.<br />

--001a113cd6641d2665055fb287da--

.