【问题标题】:Apple clang and C++20 operator ambiguity with inherited comparison operatorApple clang 和 C++20 运算符歧义与继承的比较运算符
【发布时间】:2021-02-05 13:07:32
【问题描述】:

今天升级了 Xcode(底层 clang 升级到了clang-1200.0.32.21),并开始出现类似here 描述的模棱两可的比较错误。但在那个例子中,缺少 const 很明显,而对我来说,问题似乎是继承的比较运算符。这是一个最小的例子:

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

所以,当使用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
         ^

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

是否存在破坏继承运算符使用的合法原因,或者这是 Apple clang 错误?

【问题讨论】:

  • 由于引入了重写的比较运算符,有很多代码会中断。一般准则是原始代码可能没有清晰/合理的语义。话虽如此,对我来说,您的代码有什么问题并不是很明显。使用基类operator== 应该没问题。也许:p
  • @cigien 好吧,是的,我可以清楚地看到强制执行适当的 constness(如链接示例中)等可能而且可能应该破坏一些东西,但在这里我只是感到困惑。
  • 不只是苹果铿锵声:godbolt.org/z/h84K3r
  • 我看到你已经接受了下面的答案。但是您的问题是“破坏代码的新规则是什么?”还是“为什么新规则会破坏我的代码,我做错了什么?我问过latter,但是那里的答案,以及这里的答案,基本上都是针对前者的。
  • @cigien 我对前者很感兴趣,因为我不知道类型互换性究竟是如何搞砸的。我可以接受新标准引入了重大更改(这很可悲),尽管在我的实际案例中,using 用于区分多个父类的运算符,这非常有影响。

标签: c++ clang++ c++20


【解决方案1】:

这是 using 声明。如果你省略它,一切都会按预期工作。基类中定义的运算符通过名称查找找到,提供单个候选(相同的隐式转换,顺序相反),一切都很好。这是 using 声明的作用

[over.match.funcs]

4 用于使用声明引入的非转换函数 在派生类中,该函数被认为是 用于定义隐式类型的派生类 对象参数。

基本上,using 声明的行为就像您声明了一样

bool operator==(const Bar&) const

Foo。因此,当名称查找找到operator== 时,左侧参数被视为Foo。该成员在重写时提供了两个候选项

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

现在我们遇到了与另一个问题完全相同的问题。不是 const 限定转换,而是派生到基础的转换。

【讨论】:

  • 谢谢,任何想法为什么 gcc 允许在 c++20 中这样做?
  • gcc 可能还没有实现这个检查(还)
  • @Rodolfs - 任何一个 GCC 都提供了一个扩展(如 Clang,但没有警告)。或者它还没有正确实现它。添加-pedantic 会改变 GCC 的行为吗?
  • @AlanBirtles 顺便说一句,我实际上有一个限制,为什么我使用using - 在实际示例中,该类继承了两个具有碰撞== 运算符的特征类,因此using 是一种解决歧义的方法。我想我会继续添加一个显式的 == 运算符,但我想这表明仅删除 using 并不是 100% 的解决方案。
  • @AlanBirtles nope,-pedantic 不会影响 gcc,所以我想它还没有。
猜你喜欢
  • 2021-11-13
  • 2021-05-02
  • 2013-10-17
  • 1970-01-01
  • 2021-09-05
  • 2010-09-27
  • 2021-04-26
  • 1970-01-01
  • 2011-07-08
相关资源
最近更新 更多