【问题标题】:Ambiguous operator overload on clangclang 上的模棱两可的运算符重载
【发布时间】:2014-09-26 10:33:16
【问题描述】:

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

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

我在 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)
                    ^

这在 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;
};

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

【问题讨论】:

  • is there a workaround so that the operator in comma_guard will always be preferred? 是的,虽然很丑:(comma_guard().operator,(foo()));
  • 您的“更新”有效,因为对于需要转换为 any 的成员,非成员更适合。
  • @T.C.是的 - 所以它实际上不是一个解决方案

标签: c++ c++11 clang language-lawyer


【解决方案1】:

根据我对 ADL 查找的理解,应该首选 comma_guard 中的成员函数,因此不应有歧义。这是正确的吗?


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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 2010-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    相关资源
    最近更新 更多