简体   繁体   English

Apple clang 和 C++20 运算符歧义与继承的比较运算符

[英]Apple clang and C++20 operator ambiguity with inherited comparison operator

Upgraded Xcode today (and underlying clang went up to clang-1200.0.32.21 ), and started getting ambiguous comparison errors like described here .今天升级了 Xcode(并且底层的 clang 升级到了clang-1200.0.32.21 ),并开始出现像这里描述的模棱两可的比较错误。 But in that example the lack of const was evident, while for me the issue seems to be an inherited comparison operator.但在那个例子中,显然缺少 const,而对我来说,问题似乎是继承的比较运算符。 Here is a minimal example:这是一个最小的例子:

struct Bar
{
    bool operator==(const Bar&) const
    {
        return true;
    }
};

struct Foo : Bar
{
    using Bar::operator==;
#if defined(USE_FOO)
    bool operator==(const Foo&) const
    {
        return true;
    }
#endif
};

int main()
{
    Foo a,b;
    if (a == b)
    {
        return 0;
    }
    else 
    {
        return 1;
    }
}

So, when compiling with clang++ -std=c++2a it gives:因此,当使用clang++ -std=c++2a编译时,它给出:

warning: ISO C++20 considers use of overloaded operator '=='
      (with operand types 'Foo' and 'Foo') to be ambiguous despite there being a
      unique best viable function [-Wambiguous-reversed-operator]
    if (a == b)
        ~ ^  ~
test.cpp:3:10: note: ambiguity is between a regular call to this operator and a
      call with the argument order reversed
    bool operator==(const Bar&) const
         ^

while clang++ -std=c++2a -DUSE_FOO works.clang++ -std=c++2a -DUSE_FOO有效。

Is there a legitimate cause that breaks use of inherited operators or is this an Apple clang bug?是否有合法的原因破坏了继承运算符的使用,或者这是 Apple 的叮当声错误?

It's the using declaration.这是 using 声明。 If you omit it, everything works as expected.如果省略它,一切都会按预期进行。 The operator defined in the base class is found by name lookup, provides a single candidate (same implicit conversions, with the order reversed) and all is well.基类中定义的运算符通过名称查找找到,提供单个候选(相同的隐式转换,顺序颠倒)并且一切正常。 Here's what the using declaration does下面是 using 声明的作用

[over.match.funcs] [over.match.funcs]

4 For non-conversion functions introduced by a using-declaration into a derived class, the function is considered to be a member of the derived class for the purpose of defining the type of the implicit object parameter. 4对于由 using 声明引入派生类的非转换函数,为了定义隐式对象参数的类型,该函数被认为是派生类的成员。

Basically, the using declaration behaves as if you declared基本上, using 声明的行为就像你声明

bool operator==(const Bar&) const

In Foo .Foo So the left argument is considered a Foo when name lookup finds operator== .因此,当名称查找找到operator==时,左参数被视为Foo This member, when re-written, provides two candidates该成员在重写时提供了两个候选人

bool operator==(const Foo&, const Bar&);
bool operator==(const Bar&, const Foo&);

And now we have the exact same problem the other question has.现在我们遇到了与另一个问题完全相同的问题。 Not with a const-qualification conversion, but a derived-to-base conversion.不是 const 限定转换,而是派生到基类的转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM