[cfe-dev] Is this a bug?

Hubert Tong via cfe-dev cfe-dev at lists.llvm.org
Sun Dec 10 21:51:17 PST 2017


As for MSVC, it seems it has some sort of off-by-one-error:
struct ty1st;
//typedef ty1st ty2nd;
struct ty2nd;

template <typename TT, typename UU>
struct A {
  template <typename T> void operator<(A<T, ty2nd> &) &;
};

template <typename T> void operator<(A<int, ty1st> &, T &);

void g(A<int, ty1st> *ap, A<void, ty2nd> *a2p) { *ap < *a2p; }

That is, the parameter type for the LHS in the non-member function seems to
be matched to that for the RHS in the non-static member function.

On Sun, Dec 10, 2017 at 10:43 PM, Hubert Tong <
hubert.reinterpretcast at gmail.com> wrote:

> GCC does not seem to care enough about the "first parameter":
> struct A {
>   template <typename T> bool operator<(T &) &; // #1
> };
>
> template <typename T> bool operator<(T &, A &); // #2
>
> void g(A *ap) { *ap < *ap; } // GCC picks #2; Clang and MSVC says ambiguous
>
> 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.
>
>
> On Sun, Dec 10, 2017 at 10:05 AM, Hubert Tong <
> hubert.reinterpretcast at gmail.com> wrote:
>
>> Converting your case:
>> template <typename T, typename Policy>
>> struct Handle
>> {
>>   template <typename Rhs> bool operator <(Rhs rhs) const;
>> };
>>
>> struct Special;
>>
>> template <typename LHS_T2, typename RHS_T2>
>> bool operator <(Handle<Special, LHS_T2> lhs, Handle<Special, RHS_T2> rhs);
>>
>> bool f() {
>>   Handle<Special, int> h1, h2;
>>   return h1 < h2;
>> }
>>
>> to
>>
>> template <typename T, typename Policy> struct Handle { };
>> struct Special;
>>
>> template <typename Rhs>
>> bool operator <(*const Handle<Special, int> &*, Rhs);
>>
>> template <typename LHS_T2, typename RHS_T2>
>> bool operator <(Handle<Special, LHS_T2>, Handle<Special, RHS_T2>);
>>
>> bool f() {
>>   Handle<Special, int> h1, h2;
>>   return h1 < h2;
>> }
>>
>> Gives the same behaviour between Clang and GCC.
>>
>> On Sun, Dec 10, 2017 at 3:11 AM, Evan Driscoll via cfe-dev <
>> cfe-dev at lists.llvm.org> wrote:
>>
>>> 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.
>>>
>>> Thanks,
>>> Evan
>>>
>>> [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/7ir4
>>> j5/-/
>>> [5] Modified copy with ref parameter: https://godbolt.org/g/v9HtuH
>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> cfe-dev at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171211/20b308ff/attachment.html>


More information about the cfe-dev mailing list