<div dir="ltr">On 10 October 2013 20:37, Gabriel Dos Reis <span dir="ltr"><<a href="mailto:gdr@axiomatics.org" target="_blank">gdr@axiomatics.org</a>></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<T*> as a<br>
| total order was never meant to be synonymous for operator< 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't true for pointers, so now we have an irregular guideline: "Except for pointers, don't provide operator< for a type unless it is the natural total order for that type."<br>
<br></div><div>It gets worse in C++14. std::less<> (aka std::less<void>) uses operator<, not std::less<T> 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<.<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't we pull it from C++14 and put it into the Lib Fundamentals TS until we understand the ramifications better? It isn't like anyone brought up this point when it was discussed in Bristol)? Or should it read: "Except for pointers, don't provide operator< for a type unless it is the natural order for that type, unless you wish to allow people to use std::less<>, in which case provide an operator< anyway."<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 "calling operator< on pointers can invoke ub at the drop of a hat", while historically necessary, is a horrible, horrible rule.<br>
</div><div><br></div><div>Changing the rule to "pointers are totally ordered with respect to the comparison operators" 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>
| "a representational order if no natural total order (operator <) is available,<br>
| otherwise the natural total order". He goes on: "They are named separately, <br>
| operator<() is the natural total order and std::less<> is the natural total<br>
| order if one exists, otherwise it is a representational order."<br>
|<br>
| Pointers clearly violate those rules.<br>
<br>
</div>Sean will speak for himself, but I don't think he was making the point<br>
that operator< on pointers was a total order. </blockquote><div><br></div><div>In other words, operator< on pointers violates his own rule, as it is NOT the natural (or even necessarily any) total order on pointers. I'm positive Sean will never have a problem living with this contradiction. But he'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 "p < q" to make<br>
sense, the addresses must be related is an expert-level thing.<br></blockquote><div><br></div><div>It's the subtle difference between std:less<T*> and operator< 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't claim that for two random iterators p and q, the<br>
expression p < 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<T*> and std::less<> (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've not seen novices wanting to do anything sensible in a conditional<br>
based on p < q when the addresses are not related.</blockquote><div><br></div><div>Really? I've seen novices ask questions like "does pointer p point to an object inside array a?" A natural (but wrong) way to write it is:<br>
<br></div><div>bool isInArray = std::begin(a) <= p && p < 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 ":-)" Liber <mailto:<a href="mailto:nevin@eviloverlord.com" target="_blank">nevin@eviloverlord.com</a>> <a href="tel:%28847%29%20691-1404" value="+18476911404" target="_blank">(847) 691-1404</a>
</div></div>