title: Is std::less supposed to allow comparison of unrelated pointers at compile-time?
body: <p>Consider this code:</p>
  <pre><code>#include &lt;functional&gt;
  #include &lt;typeinfo&gt;
  
  template &lt;typename T&gt;
  inline constexpr const void *foo = &amp;typeid(T);
  
  int main()
  {
      constexpr bool a = std::less&lt;const void*&gt;{}(foo&lt;int&gt;, foo&lt;float&gt;);
  } 
  </code></pre>
  <p><kbd><a href="https://gcc.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(fontScale:14,j:1,lang:c%2B%2B,selection:(endColumn:47,endLineNumber:5,positionColumn:47,positionLineNumber:5,selectionStartColumn:47,selectionStartLineNumber:5,startColumn:47,startLineNumber:5),source:%27%23include+%3Cfunctional%3E%0A%23include+%3Ctypeinfo%3E%0A%0Atemplate+%3Ctypename+T%3E%0Ainline+constexpr+const+void+*foo+%3D+%26typeid(T)%3B%0A%0Aint+main()%0A%7B%0A++++constexpr+bool+a+%3D+std::less%3Cconst+void*%3E%7B%7D(foo%3Cint%3E,+foo%3Cfloat%3E)%3B%0A%7D+%0A%27),l:%275%27,n:%270%27,o:%27C%2B%2B+source+%231%27,t:%270%27)),k:52.17506098630851,l:%274%27,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((g:!((h:compiler,i:(compiler:clang1000,filters:(b:%270%27,binary:%271%27,commentOnly:%270%27,demangle:%270%27,directives:%270%27,execute:%270%27,intel:%270%27,libraryCode:%271%27,trim:%271%27),fontScale:13,j:2,lang:c%2B%2B,libs:!(),options:%27-std%3Dc%2B%2B2a+-Wall+-Wextra+-pedantic-errors%27,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:%275%27,n:%270%27,o:%27x86-64+clang+10.0.0+(Editor+%231,+Compiler+%232)+C%2B%2B%27,t:%270%27)),header:(),k:45.04027643353199,l:%274%27,m:50,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((h:output,i:(compiler:2,editor:1,fontScale:10,wrap:%271%27),l:%275%27,n:%270%27,o:%27%232+with+x86-64+clang+10.0.0%27,t:%270%27)),header:(),l:%274%27,m:50,n:%270%27,o:%27%27,s:0,t:%270%27)),k:47.8249390136915,l:%273%27,n:%270%27,o:%27%27,t:%270%27)),l:%272%27,n:%270%27,o:%27%27,t:%270%27)),version:4" rel="noreferrer">Run on gcc.gotbolt.org</a></kbd></p>
  <p>If I use <code>&lt;</code> instead of <code>std::less</code> here, the code doesn't compile. This is not surprising, because the result of a relational pointer comparsion is <a href="https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_comparison_operators" rel="noreferrer">unspecified</a> if the pointers point to unrelated objects, and apparently such a comparsion can't be done at compile-time.</p>
  <blockquote>
  <pre class="lang-none prettyprint-override"><code>&lt;source&gt;:9:20: error: constexpr variable 'a' must be initialized by a constant expression
      constexpr bool a = foo&lt;int&gt; &lt; foo&lt;float&gt;;
                     ^   ~~~~~~~~~~~~~~~~~~~~~
  &lt;source&gt;:9:33: note: comparison has unspecified value
      constexpr bool a = foo&lt;int&gt; &lt; foo&lt;float&gt;;
                                  ^
  </code></pre>
  </blockquote>
  <p>The code still doesn't compile, even if I use <code>std::less</code>. The compiler error is the same. <code>std::less</code> appears to be implemented as <code>&lt;</code> in at least libstdc++ and libc++; I get the same results on GCC, Clang, and MSVC.</p>
  <p>However, the cppreference page about <a href="https://en.cppreference.com/w/cpp/utility/functional/less" rel="noreferrer"><code>std::less</code></a> claims that:</p>
  <ol>
  <li><p>Its <code>operator()</code> is <code>constexpr</code>.</p>
  </li>
  <li><p>It magically implements strict total order on pointers, i.e. can be used to compare unrelated pointers with sensible results.</p>
  </li>
  </ol>
  <p>So, is it a bug in all those compilers, or am I missing some detail about <code>std::less</code> that makes the code above ill-formed?</p>