<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Jan 16, 2014 at 11:38 AM, Herb Sutter <span dir="ltr">&lt;<a href="mailto:hsutter@microsoft.com" target="_blank">hsutter@microsoft.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">





<div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">Richard, it cannot mean that (or if it does, IMO we have an obvious bug) for at least two specific reasons I can think of (below), besides the general reasons
 that it would not be sensical and would violate type safety.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">First, objects must have unique addresses. Consider, still assuming B is trivially constructible:<u></u><u></u></span></p>

<p class="MsoNormal">  void *p = malloc(sizeof(B));<u></u><u></u></p>
<p class="MsoNormal">  B* pb = (B*)p;<br>
  pb-&gt;i = 0;<u></u><u></u></p>
<p class="MsoNormal">  short* ps = (short*)p;<br>
  *ps = 0;<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">This cannot possibly be construed as starting the lifetime of a B object and a short object, else they would have the same address, which is illegal. Am I missing
 something?<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">Second, this function:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">    template&lt;typename T&gt; T* test() {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">        auto p = (T*)malloc(sizeof(T));<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">        new (p) T{};<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">        return p;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">    }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">clearly returns a pointer to a T object for any default-constructible type T – and that has to be true whether or not T is trivially constructible.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">If the current rules are as Richard says, then it would true that test() returns a pointer to a T, unless T is trivially constructible in which case it returns
 a pointer to anything of size T. That doesn’t make any sense, and if the rules say that now I’d say we have a defect.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">The more I see about this, the more I think the lifetime wording (a) is correct for non-trivial-ctor cases and (b) is incomplete or incorrect for trivial-ctor
 cases.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">In particular, untyped storage (such as returned from malloc) should never be considered of any type T
<i>until after the possibly-trivial T::T has run</i>, such as via placement new. Note I include “possibly-trivial” there on purpose. If you don’t call a T ctor, you don’t have a T object – that
<i>has</i> to be true. Otherwise don’t we have multiple contradictions in the standard?<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">“It’s not a T until the T ctor runs” has to be part of the rules somewhere. It is there for non-trivially-constructible types.<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">Do we have a defect here that we’re missing that rule for trivially-constructible types?</span></p>
</div></div></blockquote><div><br></div><div>I agree that something is missing from the rules. I&#39;m not convinced that &quot;it&#39;s not a T until the T ctor runs&quot; is the right fix. Mostly it&#39;s just that I don&#39;t understand what the consequences of that rule would be, and the standard would have to say something about those consequences. So consider the following snippet:</div>
<div>  struct T { int x; };</div><div>  T x{17}; // 1</div><div>  void* pv = malloc(sizeof(T)); // 2</div><div>  T* p = static_cast&lt;T*&gt;(pv); // 3</div><div>  *p = x;  // 4</div><div><br></div><div>I&#39;m trying to understand what your rule would imply for that snippet. Does your rule imply that line 4 is undefined behavior (since, according to your proposed rule, *p isn&#39;t an object of type T)? Or does your rule imply that *p is an object of type T after line 4 (maybe an assignment might count as the moral equivalent of a constructor)? Or does your rule imply that this code snippet is well defined, and that *p may be used to do (some of) the things you can do with an object of type T but that it is not in fact an object of type T?</div>
<div><br></div><div>I&#39;m afraid I&#39;m just not sure this is a fruitful line of reasoning. All three of those possible followups to your rule have odd consequences. Maybe there&#39;s a fourth option I&#39;m not seeing, or maybe it means we need a different fix.</div>
<div><br></div><div>                         --Matt</div></div></div></div>