C++ clang上的模糊运算符重载

C++ clang上的模糊运算符重载,c++,c++11,clang,language-lawyer,C++,C++11,Clang,Language Lawyer,当我尝试编译此测试程序时: 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() {

当我尝试编译此测试程序时:

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());
}
< C++ >

哪个是正确的? 从我对ADL查找的理解来看,应该首选逗号_-guard中的成员函数,因此不应该含糊不清。这是正确的吗


回答:在重载解析期间,根据标准§13.3.1/2&7候选函数和参数列表[over.match.funcs]:

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

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

[脚注
126
]参数推导过程完全决定了函数模板专门化的参数类型,即函数模板专门化的参数不包含模板参数类型。因此,除非另有规定 否则,函数模板专门化和非模板函数(8.3.5)在重载解析的剩余部分中被同等对待

因此,模板成员重载运算符在重载解析拾取方面没有比模板自由重载运算符具有更高的优先级

即使它有GCC选择自由模板重载操作符

因此,在我看来,GCC表现出不符合标准的行为,而Clang理所当然地抱怨超负荷解决的模糊性


此外,是否有一个变通办法,以便始终首选逗号_-guard中的操作员



回答:是的,尽管有点难看:
(逗号_-guard().operator,(foo())

是否有一种解决方法,使逗号保护中的运算符始终是首选的?
是的,但很难看:
(逗号保护().operator,(foo())
您的“更新”有效,因为对于需要转换为
any
的成员,非成员更匹配。@T.C.true-因此它实际上不是解决方案
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)
                    ^
struct comma_guard
{
    struct any
    {
        template<class T>
        any(T&&);
    };
    const comma_guard& operator,(any) const;
};