[cfe-dev] Is this a bug?

Evan Driscoll via cfe-dev cfe-dev at lists.llvm.org
Sun Dec 10 00:11:27 PST 2017

In our code base, we have the following (code linked below):

* A class template for "handles" to objects of assorted types,
  Handle<T, Policy>; T is the actual element type
* Handle contains a member operator < (and others). It uses the
  "address" of the object to do the comparison.
* There is a special class where we want to customize operator <
  so it looks into the associated object, so we have a templated
  overload free function of operator< on Handle<Special, T2>.

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.

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].

Perhaps importantly, the operator< member of Handle has this "signature":

   template <typename T, typename Policy>
   template <typename RHS_Handle>
   bool Handle<T, Policy>::operator< (RHS_Handle const &)

and the free function has this signature:

    template <
        typename LHS_T, typename LHS_Policy,
        typename RHS_T, typename RHS_Policy>
    bool operator<  (
        Handle<LHS_T, LHS_Policy> lhs,
        Handle<RHS_T, RHS_Policy> rhs);

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.

So if the function is called with

    Handle<MyType, SomePolicy> h1, h2;
    h1 < h2;

then it should not be ambiguous, and select the free overload. However,
perhaps the cv-qualification matters, and GCC/MSVC get it wrong?

Credit to OmegaNaughtEquals1 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].

If I change the free function to take 'lhs' by reference, then Clang
compiles it [5].

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.


[1] GCC compiles it: https://godbolt.org/g/9EaoYh
[2] MSVC does too: https://godbolt.org/g/ubXeC3
[3] Clang's error: https://godbolt.org/g/MhNEky
[4] Reddit thread: https://www.reddit.com/r/cpp_questions/comments/7ir4j5/-/
[5] Modified copy with ref parameter: https://godbolt.org/g/v9HtuH
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171210/88621117/attachment.html>

More information about the cfe-dev mailing list