<div dir="auto">Since when is the ability to run your code in the compiler the driving force behind what C++ should be?  Seems like a silly goal.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Apr 30, 2021, 11:07 AM Tom Honermann &lt;<a href="mailto:tom@honermann.net">tom@honermann.net</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div>
    <div>On 4/30/21 10:16 AM, Hyman Rosen via
      Std-Discussion wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="auto">This is where the conceptual error of the C++
        object model shows. A pointer or reference points to memory, not
        to an object. The pointer type informs how that memory should be
        treated.  If the memory remains allocated to the program, the
        pointer is valid. If the contents of the memory are valid for a
        type, the object of that type in that memory is valid.</div>
    </blockquote>
    <p>I tried to point this out elsewhere in this thread, but I&#39;m not
      sure the point landed.</p>
    <p>If the C++ object model worked as you state it should, then
      constexpr evaluation would not be feasible or would be more
      constrained than it currently is.  With a memory based model, the
      implementation would have to mimic memory layout for the target
      architecture in order for code to behave the same at compile-time
      vs run-time.  The C++ object model avoids that by allowing the
      implementation to represent objects differently during constant
      evaluation, but in a way that isn&#39;t observable.  This does put
      some constraints on what operations can be performed at
      compile-time (e.g., no <tt>reinterpret_cast</tt>), but allows a
      clear subset of the language to be used in both evaluation
      contexts.</p>
    <p>Just to make that a little more concrete, here is an example that
      mimics a vector insert operation (including use of placement new
      as would be done by <tt>std::allocator</tt>).  All major
      compilers reject the example.  If <tt>constexpr</tt> is removed
      from the declaration of <tt>f()::v</tt>, some compilers still
      reject it (I assume the ones that accept it do so as a conforming
      extension, but I&#39;m not sure).  For those that accept it, they do
      (currently) behave as you describe; the dereference of the pointer
      yields the value of the replacement object, including under
      optimization.<br>
    </p>
    <p><a href="https://www.godbolt.org/z/Kffzbn8jh" target="_blank" rel="noreferrer">https://www.godbolt.org/z/Kffzbn8jh</a><br>
    </p>
    <p><tt>#include &lt;cassert&gt;</tt><tt><br>
      </tt><tt>#include &lt;utility&gt;</tt><tt><br>
      </tt><tt>#include &lt;new&gt;</tt><tt><br>
      </tt><tt>using T = int;</tt><tt><br>
      </tt><tt>constexpr T insert(T i) {</tt><tt><br>
      </tt><tt>  T a[3] = { 1, 3 };</tt><tt><br>
      </tt><tt>  T *p = &amp;a[1];</tt><tt><br>
      </tt><tt>  a[2] = std::move(a[1]);</tt><tt><br>
      </tt><tt>  new (&amp;a[1]) T{i};</tt><tt><br>
      </tt><tt>  return *p;</tt><tt><br>
      </tt><tt>}</tt><tt><br>
      </tt><tt>void f() {</tt><tt><br>
      </tt><tt>  constexpr T v = insert(2);</tt><tt><br>
      </tt><tt>  assert(v == 2);</tt><tt><br>
      </tt><tt>}</tt><br>
    </p>
    <p>It would perhaps be feasible to make the above example work in
      limited circumstances if we allowed placement new to replace an
      existing object of the same type (that is not so different from an
      assignment after all).  C++20 constexpr vector support avoids this
      question by special casing <tt>std::allocator</tt> at
      compile-time.<br>
    </p>
    <p>Tom.<br>
    </p>
    <blockquote type="cite">
      <div dir="auto">
        <div dir="auto"><br>
        </div>
        <div dir="auto">Your deciding for all programmers that when they
          have pointers to vector elements they &quot;really&quot; mean some
          theoretical element that wanders around within the vector is
          no more valid than if you decided the same for pointers to
          array elements. You are breaking people&#39;s code or making it
          harder for them to work so that you can satisfy yourself about
          some useless abstract principle being followed. </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Fri, Apr 30, 2021, 9:33 AM
          Jason McKesson via Std-Discussion &lt;<a href="mailto:std-discussion@lists.isocpp.org" target="_blank" rel="noreferrer">std-discussion@lists.isocpp.org</a>&gt;
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Fri, Apr
          30, 2021 at 7:37 AM Giuseppe D&#39;Angelo via Std-Discussion<br>
          &lt;<a href="mailto:std-discussion@lists.isocpp.org" rel="noreferrer noreferrer" target="_blank">std-discussion@lists.isocpp.org</a>&gt;
          wrote:<br>
          &gt;<br>
          &gt; Hello,<br>
          &gt;<br>
          &gt; On 30/04/2021 01:56, Jason McKesson via Std-Discussion
          wrote:<br>
          &gt; &gt;<br>
          &gt; &gt; By inserting an object into a vector, you have
          conceptually changed<br>
          &gt; &gt; the address of all of the objects past that one in
          the container.<br>
          &gt; &gt; However, any pointers/references cannot themselves
          move to aim at the<br>
          &gt; &gt; correct object. Therefore, such pointers/references
          should no longer<br>
          &gt; &gt; be considered valid pointers/references to what they
          pointed<br>
          &gt; &gt; to/referenced.<br>
          &gt; &gt;<br>
          &gt; &gt; Put simply, a pointer/reference to an element in a
          container is not,<br>
          &gt; &gt; and should not be considered, a fancy index.<br>
          &gt;<br>
          &gt; I never said that pointers/references/iterators should
          magically move.<br>
          &gt; In fact, I said that pointers would point to the element
          that ends up<br>
          &gt; being in the position they were pointing to.<br>
          <br>
          My point is that they *should* &quot;move&quot;. A pointer to an element
          should<br>
          be a pointer to that element and no other element, unless you<br>
          explicitly modify that element. Because the nature of `vector`
          makes<br>
          that impossible implementation-wise, the only reasonable
          alternative<br>
          is to make them invalid.<br>
          <br>
          &gt; You&#39;re basically arguing that &quot;it is what it is&quot;
          regarding the lack of<br>
          &gt; such a guarantee. That is, the mental model that `vector`
          to go with is<br>
          &gt; a mental model that invalidates pointers, even if:<br>
          &gt;<br>
          &gt; * such invalidation is unenforceable (unlike iterators);<br>
          &gt; * such invalidation doesn&#39;t actually happen in any
          implementation (are<br>
          &gt; implementations allowed to have extra capacity on the
          left to optimize<br>
          &gt; prepend? That makes a mess out of capacity(), but maybe
          there&#39;s an<br>
          &gt; escape hatch/hat trick);<br>
          &gt; * such invalidation cannot even happen because of (new?
          old?) language<br>
          &gt; rules (unlike iterators, and due to a lack of an ad-hoc<br>
          &gt; `std::invalidate` facility) and therefore it&#39;s not usable
          in<br>
          &gt; optimizations, sanitizers, etc.;<br>
          &gt; * it costs precisely zero for an implementation provide
          the extra<br>
          &gt; guarantee (in fact, is it already &quot;accidentally&quot; offered
          today by all<br>
          &gt; implementations?).<br>
          &gt;<br>
          &gt; I&#39;m not sure if I&#39;m 100% convinced. A `vector` isn&#39;t an
          arbitrary data<br>
          &gt; structure, it&#39;s a quite specific one, with clear
          operational semantics.<br>
          <br>
          But it is a container, and it should act like one. Pointers to<br>
          elements in a container should act like pointer to elements in
          every<br>
          other container, except for when that is made impossible by
          some<br>
          specific nature of a specific container. And in those cases,
          those<br>
          pointers should be invalidated; they shouldn&#39;t do something
          weird like<br>
          magically transform into pointers to other elements.<br>
          <br>
          And I&#39;d like to point out that there&#39;s not really any
          practical<br>
          benefit to creating a special rule like this for `vector`.
          That is, it<br>
          doesn&#39;t let you do anything you couldn&#39;t do with indices if
          you know<br>
          you&#39;re working with a `vector`. So you should just use indices
          to make<br>
          it clear to everyone reading your code that you expect the
          underlying<br>
          elements to shift around.<br>
          <br>
          In any case, you wanted to understand the conceptual reasoning
          behind<br>
          it, and this is it. You don&#39;t have to agree with it, but this
          is the<br>
          logic behind it.<br>
          -- <br>
          Std-Discussion mailing list<br>
          <a href="mailto:Std-Discussion@lists.isocpp.org" rel="noreferrer noreferrer" target="_blank">Std-Discussion@lists.isocpp.org</a><br>
          <a href="https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion" rel="noreferrer noreferrer noreferrer" target="_blank">https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion</a><br>
        </blockquote>
      </div>
      <br>
      <fieldset></fieldset>
    </blockquote>
    <p><br>
    </p>
  </div>

</blockquote></div>

