<div dir="ltr"><div>GCC does not seem to care enough about the "first parameter":<br>struct A {<br>  template <typename T> bool operator<(T &) &; // #1<br>};<br><br>template <typename T> bool operator<(T &, A &); // #2<br><br>void g(A *ap) { *ap < *ap; } // GCC picks #2; Clang and MSVC says ambiguous<br><br></div>Given that the constrained and unconstrained parameters are similar in their constrainedness between the two candidates (just with different ordering), and the arguments provided match just as well: it seems to me that what GCC does is broken here.<br><div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Dec 10, 2017 at 10:05 AM, Hubert Tong <span dir="ltr"><<a href="mailto:hubert.reinterpretcast@gmail.com" target="_blank">hubert.reinterpretcast@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>Converting your case:<span class=""><br>template <typename T, typename Policy><br></span>struct Handle<br>{<br>  template <typename Rhs> bool operator <(Rhs rhs) const;<br>};<br><br>struct Special;<br><br>template <typename LHS_T2, typename RHS_T2><br>bool operator <(Handle<Special, LHS_T2> lhs, Handle<Special, RHS_T2> rhs);<br><br>bool f() {<br>  Handle<Special, int> h1, h2;<br>  return h1 < h2;<br>}<br><br>to<br><br>template <typename T, typename Policy> struct Handle { };<br>struct Special;<br><br>template <typename Rhs><br>bool operator <(<b>const Handle<Special, int> &</b>, Rhs);<br><br>template <typename LHS_T2, typename RHS_T2><br>bool operator <(Handle<Special, LHS_T2>, Handle<Special, RHS_T2>);<br><br>bool f() {<br>  Handle<Special, int> h1, h2;<br>  return h1 < h2;<br>}<br><br></div>Gives the same behaviour between Clang and GCC.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Sun, Dec 10, 2017 at 3:11 AM, Evan Driscoll via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr"><font face="monospace, monospace">In our code base, we have the following (code linked below):<br><br>* A class template for "handles" to objects of assorted types, </font><div><font face="monospace, monospace">  Handle<T, Policy>; T is the actual element type</font></div><div><font face="monospace, monospace">* Handle contains a member operator < (and others). It uses the </font></div><div><font face="monospace, monospace">  "address" of the object to do the comparison.<br>* There is a special class where we want to customize operator < </font></div><div><font face="monospace, monospace">  so </font><span style="font-family:monospace,monospace">it looks into the associated object, so we have a templated </span></div><div><font face="monospace, monospace">  overload free function of operator< on Handle<Special, T2>.<br><br>I've got my doubts as to the sanity of this design in some ways, but I don't think I can reasonably change it.<br><br>This compiles with GCC [1], and with MSVC [2], but Clang gives an error about the two operator<s being ambiguous, starting with 3.5 [3].</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Perhaps importantly, the operator< member of Handle has this "signature":</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">   template <typename T, typename Policy></font></div><div><font face="monospace, monospace">   template <typename RHS_Handle></font></div><div><font face="monospace, monospace">   bool Handle<T, Policy>::operator< (RHS_Handle const &)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">and the free function has this signature:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    template <</font></div><div><font face="monospace, monospace">        typename LHS_T, typename LHS_Policy,</font></div><div><font face="monospace, monospace">        typename RHS_T, typename RHS_Policy></font></div><div><font face="monospace, monospace">    bool operator<  (</font></div><div><font face="monospace, monospace">        Handle<LHS_T, LHS_Policy> lhs,</font></div><div><font face="monospace, monospace">        Handle<RHS_T, RHS_Policy> rhs);</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">At least if we ignore the references and cv-quals, my understanding is that the latter function should have priority over the former because it's more specialized -- the second parameter is Handle<RHS_T, RHS_Policy> rather than a generic RHS_Handle type.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">So if the function is called with </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    Handle<MyType, SomePolicy> h1, h2;</font></div><div><font face="monospace, monospace">    h1 < h2;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">then it should not be ambiguous, and select the free overload. However, perhaps the cv-qualification matters, and GCC/MSVC get it wrong?</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Credit to OmegaNaughtEquals1</font><span style="font-family:monospace,monospace"> on Reddit who pointed me to some standards text that seems to support the position that it should work (maybe... it's too late to really tell what should be happening with the cv/ref stuff) [4].</span></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">If I change the free function to take 'lhs' by reference, then Clang compiles it [5].</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I'm happy to report this to the bug tracker if that's what I should do -- I just wasn't sure if I should with something that I'm not sure is a bug.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Thanks,</font></div><div><font face="monospace, monospace">Evan</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">[1] GCC compiles it: <a href="https://godbolt.org/g/9EaoYh" target="_blank">https://godbolt.org/g/9Eao<wbr>Yh</a></font></div><div><font face="monospace, monospace">[2] MSVC does too: <a href="https://godbolt.org/g/ubXeC3" target="_blank">https://godbolt.org/g/ubX<wbr>eC3</a></font></div><div><font face="monospace, monospace">[3] Clang's error: <a href="https://godbolt.org/g/MhNEky" target="_blank">https://godbolt.org/g/M<wbr>hNEky</a></font></div><div><font face="monospace, monospace">[4] Reddit thread: <a href="https://www.reddit.com/r/cpp_questions/comments/7ir4j5/-/" target="_blank">https://www.reddit.com<wbr>/r/cpp_questions/comments/7ir4<wbr>j5/-/</a></font></div><div><font face="monospace, monospace">[5] Modified copy with ref parameter: <a href="https://godbolt.org/g/v9HtuH" target="_blank">https://godbolt.org<wbr>/g/v9HtuH</a></font></div></div>
<br></div></div>______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>