clang上的模糊运算符重载

Pau*_* II 12 c++ clang language-lawyer c++11

当我尝试编译这个测试程序时:

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());
}
Run Code Online (Sandbox Code Playgroud)

我在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)
                    ^
Run Code Online (Sandbox Code Playgroud)

这在gcc上编译得很好.根据我对ADL查找的理解,成员函数comma_guard应该是首选的,因此不应该是模糊的.它是否正确?这是clang中的错误吗?此外,是否有一个解决方法,以便comma_guard始终首选操作员?

更新:所以看起来clang并不认为它是模板成员的模板.所以如果我这样定义comma_guard,它将起作用:

struct comma_guard
{
    struct any
    {
        template<class T>
        any(T&&);
    };
    const comma_guard& operator,(any) const;
};
Run Code Online (Sandbox Code Playgroud)

根据C++,哪个是正确的?

101*_*010 13

根据我对ADL查找的理解,comma_guard中的成员函数应该是首选的,因此不应该含糊不清.它是否正确?


答案:在重载过程中并根据标准§13.3.1/ 2和7候选函数和参数列表[over.match.funcs]:

2 候选函数集可以包含要针对同一参数列表解析的成员函数和非成员函数.

7在候选者是函数模板的每种情况下,使用模板参数推导(14.8.3,14.8.2)生成候选函数模板特化.然后以通常的方式将这些候选人作为候选函数处理[126].

[脚注126]参数推导过程完全确定了函数模板特化的参数类型,即函数模板特化的参数不包含模板参数类型.因此,除非另有说明,否则函数模板特化和非模板函数(8.3.5)将等效地处理重载决策的其余部分.

因此,模板成员重载运算符在重载决策选择方面没有比无模板重载运算符更高的优先级.

即使它有GCC选择免费模板重载运算符LIVE DEMO.

所以在我看来,这是GCC,它显示了一个非标准的兼容行为,并且Clang正确地抱怨过载解决方案的模糊性.


此外,是否有一个解决方法,以便comma_guard中的操作员始终是首选?


答:是的虽然有点难看:(comma_guard().operator,(foo())); LIVE DEMO