<div dir="ltr">On 10 October 2013 20:37, Gabriel Dos Reis <span dir="ltr">&lt;<a href="mailto:gdr@axiomatics.org" target="_blank">gdr@axiomatics.org</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">

<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>
|     As observed by Sean Parent in another discussion, std::less&lt;T*&gt; as a<br>
|     total order was never meant to be synonymous for operator&lt; on pointers.<br></div></blockquote><div><br></div><div>But his rule states that if it is provided for a type, it should be a natural total order for objects of that type.  That obviously isn&#39;t true for pointers, so now we have an irregular guideline:  &quot;Except for pointers, don&#39;t provide operator&lt; for a type unless it is the natural total order for that type.&quot;<br>



<br></div><div>It gets worse in C++14.  std::less&lt;&gt; (aka std::less&lt;void&gt;) uses operator&lt;, not std::less&lt;T&gt; under the covers, and even though that has weasel words about comparing pointers, it is not useable if your type does not have an operator&lt;.<br>



<br></div><div>So now what should the guideline be?  Tell people to ignore instead of embrace this addition to C++14 (in which case, shouldn&#39;t we pull it from C++14 and put it into the Lib Fundamentals TS until we understand the ramifications better?  It isn&#39;t like anyone brought up this point when it was discussed in Bristol)?  Or should it read: &quot;Except for pointers, don&#39;t provide operator&lt; for a type unless it is the natural order for that type, unless you wish to allow people to use std::less&lt;&gt;, in which case provide an operator&lt; anyway.&quot;<br>



<br></div><div>The only way to make the language and library novice-friendly is to make simpler, more regular rules with fewer exception cases.<br><br></div><div>The current rule of &quot;calling operator&lt; on pointers can invoke ub at the drop of a hat&quot;, while historically necessary, is a horrible, horrible rule.<br>



</div><div><br></div><div>Changing the rule to &quot;pointers are totally ordered with respect to the comparison operators&quot; is much more sane (and is only one step to unravelling the expert-only mess we have with relation operators in the standard).<br>



</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>
| Sean also says in [c++std-lib-ext-550]: The definition of std::less should be<br>
| &quot;a representational order if no natural total order (operator &lt;) is available,<br>
| otherwise the natural total order&quot;.  He goes on: &quot;They are named separately, <br>
| operator&lt;() is the natural total order and std::less&lt;&gt; is the natural total<br>
| order if one exists, otherwise it is a representational order.&quot;<br>
|<br>
| Pointers clearly violate those rules.<br>
<br>
</div>Sean will speak for himself, but I don&#39;t think he was making the point<br>
that operator&lt; on pointers was a total order. </blockquote><div><br></div><div>In other words, operator&lt; on pointers violates his own rule, as it is NOT the natural (or even necessarily any) total order on pointers.  I&#39;m positive Sean will never have a problem living with this contradiction.  But he&#39;s an expert...<br>



</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> I must confess I do not understand why saying that for &quot;p &lt; q&quot; to make<br>
sense,  the addresses must be related is an expert-level thing.<br></blockquote><div><br></div><div>It&#39;s the subtle difference between std:less&lt;T*&gt; and operator&lt; that makes it an expert-level thing.<br>

</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Certainly, we don&#39;t claim that for two random iterators p and q, the<br>
expression p &lt; q must make sense whether p and q are related.  Are we?<br></blockquote><div><br></div><div>Pointers are used for more than just iteration, and we already say that pointers are totally ordered with respect to std::less&lt;T*&gt; and std::less&lt;&gt; (as well as the other ordered comparators).<br>

</div><div> </div>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I&#39;ve not seen novices wanting to do anything sensible in a conditional<br>
based on p &lt; q when the addresses are not related.</blockquote><div><br></div><div>Really?  I&#39;ve seen novices ask questions like &quot;does pointer p point to an object inside array a?&quot;  A natural (but wrong) way to write it is:<br>

<br></div><div>bool isInArray = std::begin(a) &lt;= p &amp;&amp; p &lt; std::end(a);</div><div><br></div><div>Can you even write this w/o possibly invoking ub?  The only way I can think of is O(n), as in:<br><br></div><div>

bool isInArray = false;<br></div><div>for (auto q = std::begin(a); q != std::end(a); ++q)<br></div><div>    if (p == q) {<br></div><div>        isInArray = true;<br></div><div>        break;<br>    }<br><br></div><div>Do we intend such simple questions to have such complicated answers?<br>

</div></div>-- <br> Nevin &quot;:-)&quot; Liber  &lt;mailto:<a href="mailto:nevin@eviloverlord.com" target="_blank">nevin@eviloverlord.com</a>&gt;  <a href="tel:%28847%29%20691-1404" value="+18476911404" target="_blank">(847) 691-1404</a>
</div></div>