<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<title>Relative comparisons and std::less&lt;T*&gt;</title>

	<style>
	p {text-align:justify}
	li {text-align:justify}
	blockquote.note
	{
		background-color:#E0E0E0;
		padding-left: 15px;
		padding-right: 15px;
		padding-top: 1px;
		padding-bottom: 1px;
	}
	ins {color:#00A000}
	del {color:#A00000}
	</style>
</head>
<body>

<address align=right>
Document number: P0594R0
<br/>
Audience: WG21
<br/>
<br/>
<a href="mailto:ville.voutilainen@gmail.com">Ville Voutilainen</a><br/>
2017-02-05<br/>
</address>
<hr/>
<h1 align=center>Relative comparisons and std::less&lt;T*&gt;</h1>

<h2>Abstract</h2>
<p>
  It was recently brought to my attention that depending on
  optimization settings, libstdc++'s std::less for pointers is not
  a total order. See <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78420">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78420</a> for the related
  bug report.
</p>
<p>
  Quite many of us have labored under the illusion that for every
  platform we have, a relative comparison for pointers will just
  work; that doesn't seem to be the case. There have been various
  library issues on this matter, but I think their priorities
  have been deemed low because, again, we thought the problem
  isn't 'real'.
</p>

<h2>What to do?</h2>

<p>
  There have been various suggestions:
  <ul>
    <li>Change the libstdc++ implementation so that it converts the pointers to uintptr_t before doing the comparison. That's a reinterpret_cast, so it makes the call operator of std::less&lt;T*&gt; not eligible for constant expressions.</li>
    <li>Change the specification of std::less&lt;T*&gt; so that its call
      operator is not
      declared constexpr.</li>
    <li>Use compiler magic in the implementation of std::less&lt;T*&gt; so
      that it can do what it does today without losing any of its capabilities.</li>
  </ul>
</p>
<p>
  The first option means that the comparison is never a constant expression.
  That's unfortunate, because for cases where the pointers point to the
  same constexpr array, the comparison is valid today and can produce
  a translation-time result.
</p>
<p>
  The second option has the same issue as the first.
</p>
<p>
  The third option probably works, but makes it harder to support
  this library with multiple compilers. The compilers would presumably
  need to implement the same magic.
</p>
<p>
  It seems that the first and second options take us ever farther
  away from a situation where std::less&lt;T*&gt; does the same
  as the built-in operator does. We seemed to be going towards
  a direction where it does all that and more, but those suggestions
  seem to make the functionality of std::less&lt;T*&gt; a more
  disjoint set from the functionality of the built-in operator.
</p>

<h2>What else we could do?</h2>

<p>
  There would still be the possibility of making pointer comparisons
  have a total order in the core language. The arguments against that seem to
  consist of the
  possibility that segmented memory models might come back, and some
  not-so-clear statements that some existing or forthcoming implementations
  use the undefined behavior to their benefit.
</p>

</body>

</html>
