<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2450: (greater|less|greater_equal|less_equal)&lt;void&gt; do not yield a total order for pointers</title>
<meta property="og:title" content="Issue 2450: (greater|less|greater_equal|less_equal)&lt;void&gt; do not yield a total order for pointers">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2450.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++17">C++17</a> status.</em></p>
<h3 id="2450"><a href="lwg-defects.html#2450">2450</a>. <code>(greater|less|greater_equal|less_equal)&lt;void&gt;</code> do not yield a total order for pointers</h3>
<p><b>Section:</b> 22.10.8 <a href="https://wg21.link/comparisons">[comparisons]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz <b>Opened:</b> 2014-10-30 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#comparisons">active issues</a> in [comparisons].</p>
<p><b>View all other</b> <a href="lwg-index.html#comparisons">issues</a> in [comparisons].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<code>less&lt;void&gt;::operator(t, u)</code> (and the same applies to the rest of <code>void</code> specializations for standard 
comparison function objects) returns <code>t &lt; u</code> even if <code>t</code> and <code>u</code> are pointers, which by 
7.6.9 <a href="https://wg21.link/expr.rel">[expr.rel]</a>/3 is undefined except if both pointers point to the same array or object. This might be 
regarded as a specification defect since the intention of N3421 is that <code>less&lt;&gt;</code> can substitute for 
<code>less&lt;T&gt;</code> in any case where the latter is applicable. <code>less&lt;void&gt;</code> can be rewritten in 
the following manner to cope with pointers:
</p>
<blockquote><pre>
template&lt;&gt; struct less&lt;void&gt;
{

  typedef <i>unspecified</i> is_transparent;

  template &lt;class T, class U&gt;
  struct pointer_overload : std::is_pointer&lt;std::common_type_t&lt;T, U&gt;&gt;
  {};

  template &lt;
    class T, class U,
    typename std::enable_if&lt;!pointer_overload&lt;T, U&gt;::value&gt;::type* = nullptr
  &gt;
  auto operator()(T&amp;&amp; t, U&amp;&amp; u) const
    -&gt; decltype(std::forward&lt;T&gt;(t) &lt; std::forward&lt;U&gt;(u))
  {
    return std::forward&lt;T&gt;(t) &lt; std::forward&lt;U&gt;(u);
  } 

  template &lt;
    class T, class U,
    typename std::enable_if&lt;pointer_overload&lt;T, U>::value>::type* = nullptr
  &gt;
  auto operator()(T&amp;&amp; t, U&amp;&amp; u) const
    -&gt; decltype(std::declval&lt;std::less&lt;std::common_type_t&lt;T, U&gt;&gt;&gt;()(std::forward&lt;T&gt;(t), std::forward&lt;U&gt;(u)))
  {
    std::less&lt;std::common_type_t&lt;T, U&gt;&gt; l;
    return l(std::forward&lt;T&gt;(t), std::forward&lt;U&gt;(u));
  }

};
</pre></blockquote>

<blockquote class="note">
<p>
This wording is relative to N4140.
</p>

<ol>
<li><p>Change 22.10.8 <a href="https://wg21.link/comparisons">[comparisons]</a> p14 as indicated:</p>
<blockquote><p>
-14- For templates <code>greater</code>, <code>less</code>, <code>greater_equal</code>, and <code>less_equal</code>, the specializations 
for any pointer type yield a total order, even if the built-in operators <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, 
<code>&gt;=</code> do not. <ins>For template specializations <code>greater&lt;void&gt;</code>, <code>less&lt;void&gt;</code>, 
<code>greater_equal&lt;void&gt;</code>, and <code>less_equal&lt;void&gt;</code>, the call operator with arguments whose common 
type <code><i>CT</i></code> is a pointer yields the same value as the corresponding comparison function object class 
specialization for <code><i>CT</i></code>.</ins>
</p></blockquote>
</li>
</ol>
</blockquote>

<p><i>[2015-02, Cologne]</i></p>

<p>
AM: Is there any way this will be resolved elsewhere? VV: No. AM: Then we should bite the bullet and deal with it here.
<p/>
MC: These diamond operators are already ugly. Making them more ugly isn't a big problem.
<p/>
JY found some issue with types that are convertible, and will reword. 
<p/>
Jeffrey suggests improved wording.
</p>

<p><i>[2015-05, Lenexa]</i></p>

<p>
STL: when diamond functions designed, this was on purpose<br/>
STL: this does go against the original design<br/>
STL: library is smarter and can give a total order<br/>
MC: given that the original design rejected this, give back to LEWG<br/>
STL: original proposal did not talk about total order<br/>
STL: don't feel strongly about changing the design<br/>
STL: no objections to taking this issue with some wording changes if people want it<br/>
MC: not happy with wording, comparing pointers &mdash; what does that mean?<br/>
STL: needs careful attention to wording<br/>
STL: want to guarantee that <code>nullptr</code> participates in total ordering<br/>
STL: all hooks into composite pointer type<br/>
MC: move from new to open with better wording<br/>
STL: to check updates to issue after Lenexa 
</p>

<p><i>[2015-06, Telecon]</i></p>

<p>
MC: STL on the hook to update. He's shipping something today so not here.<br/>
MC: also add link to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4229.pdf">N4229</a><br/>
</p>

<p><i>[2015-10, Kona Saturday afternoon]</i></p>

<p>
STL was on the hook for wording, but STL: I don't care. The architecture on which this is an issue does not exist.<br/>
STL: We will also need to incorporate nullptr. TK: I think that's implied, since the wording is in terms of the resulting operation, not the deduced types. <br/>
STL: Seems legit. MC: I guess I'm OK with this. TK: I'm weakly in favour, so that we can get people to use transparent comparators without worrying. <br/>
STL: There's no change to implementations.<br/>
Move to Tentatively ready.
</p>


<p id="res-2450"><b>Proposed resolution:</b></p>
<p>
This wording is relative to N4296.
</p>

<ol>
<li><p>Change 22.10.8 <a href="https://wg21.link/comparisons">[comparisons]</a> p14 as indicated:</p>
<blockquote><p>
-14- For templates <code>greater</code>, <code>less</code>, <code>greater_equal</code>, and <code>less_equal</code>, the specializations 
for any pointer type yield a total order, even if the built-in operators <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, 
<code>&gt;=</code> do not. <ins>For template specializations <code>greater&lt;void&gt;</code>, <code>less&lt;void&gt;</code>, 
<code>greater_equal&lt;void&gt;</code>, and <code>less_equal&lt;void&gt;</code>, if the call operator calls a built-in operator 
comparing pointers, the call operator yields a total order.</ins>
</p></blockquote>
</li>
</ol>





</body>
</html>
