Ambiguous operator overload on clang

大兔子大兔子 提交于 2020-11-28 04:39:37

问题


When I try to compile this test program:

struct comma_guard
{
    template<class T>
    const comma_guard& operator,(T&&) const
    {
        return *this;
    }
};

struct foo {};
template<class T> T operator,(T x, foo)
{
    return x;
}

int main()
{
    (comma_guard(), foo());
}

I get a compile error on clang:

comma_guard.cpp:20:19: error: use of overloaded operator ',' is ambiguous (with operand types 'comma_guard' and 'foo')
    (comma_guard(), foo());
     ~~~~~~~~~~~~~^ ~~~~~
comma_guard.cpp:6:24: note: candidate function [with T = foo]
    const comma_guard& operator,(T&&) const
                       ^
comma_guard.cpp:13:21: note: candidate function [with T = comma_guard]
template<class T> T operator,(T x, foo)
                    ^

This compiles fine on gcc. From my understanding of ADL lookup, the member function in comma_guard should be preferred and so therefore shouldn't be ambiguous. Is this correct? Is this a bug in clang? Also, is there a workaround so that the operator in comma_guard will always be preferred?

Update: So it seems clang doesn't consider it a class member when its templated. So if I define the comma_guard like this, it will work:

struct comma_guard
{
    struct any
    {
        template<class T>
        any(T&&);
    };
    const comma_guard& operator,(any) const;
};

Which is correct according to C++?


回答1:


From my understanding of ADL lookup, the member function in comma_guard should be preferred and so therefore shouldn't be ambiguous. Is this correct?


Answer: During overload resolution and according to the standard § 13.3.1/2 & 7 Candidate functions and argument lists [over.match.funcs]:

2 The set of candidate functions can contain both member and non-member functions to be resolved against the same argument list.

7 In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction (14.8.3, 14.8.2). Those candidates are then handled as candidate functions in the usual way [126].

[footnote 126] The process of argument deduction fully determines the parameter types of the function template specializations, i.e., the parameters of function template specializations contain no template parameter types. Therefore, except where specified otherwise, function template specializations and non-template functions (8.3.5) are treated equivalently for the remainder of overload resolution.

Consequently, the template member overloaded operator hasn't have greater priority in terms of overload resolution picking than the template free overloaded operator.

Even if it had GCC picks the free template overloaded operator LIVE DEMO.

So in my humble opinion, here is GCC that shows a non standard compliant behaviour and Clang rightfully complains about overload resolution ambiguity.


Also, is there a workaround so that the operator in comma_guard will always be preferred?


Answer: Yes although kinda ugly: (comma_guard().operator,(foo())); LIVE DEMO



来源:https://stackoverflow.com/questions/25110429/ambiguous-operator-overload-on-clang

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!