【问题标题】:Overload Resolution/Ambiguity in name lookup(which one)名称查找中的重载分辨率/歧义(哪一个)
【发布时间】:2010-11-09 03:14:50
【问题描述】:

$7.3.3/14 (C++03)

struct A { int x(); };
struct B : A { };
struct C : A {
   using A::x;
   int x(int);
};
struct D : B, C {
   using C::x;
   int x(double);
};
int f(D* d) {
   return d->x(); // ambiguous: B::x or C::x
}

'f' 中代码中的注释表明可以预期 'B::x' 或 'C::x' 之间存在歧义。

但是,在使用 g++(ideone) 或 Comeau 编译时,错误略有不同。这些错误不是表示 B::x 或 C::x 中的歧义,而是表明 A 是 D 的歧义基这一事实

prog.cpp:在函数“int f(D*)”中: prog.cpp:16:错误:“A”是 ‘D’的模棱两可的基础

还有

“ComeauTest.c”,第 21 行:错误:base “A”类不明确 返回 d->x(); // 模棱两可:B::x 或 C::x

按照 $10.2 中的名称查找规则,我觉得代码 sn-p 中的注释并不真正正确。该错误确实首先与基类“A”的歧义有关,而不是其他任何事情(例如重载决议中的歧义)。有什么想法吗?

【问题讨论】:

  • 有趣的是,Visual C++ 10.0编译了上面的,选择B中的A子对象...如果它选择C中的A子对象我可以理解它。似乎g ++和Comeau首先解析了成员函数作为 A::x(),然后他们发现 d->A::x() 是模棱两可的。但是,有趣的是,Visual C++ 10.0 甚至可以编译!
  • @Alf P. Steinbach:是的。我也很惊讶
  • 由于我没有C++03编译器,希望大家能容忍这个问题... struct D中virtual关键字的使用怎么样:virtual B, C or struct D:虚拟C,虚拟B?

标签: c++ ambiguity overload-resolution name-lookup


【解决方案1】:

这是由 C++03 中名称查找的一个扭曲引起的:检查明确的子对象是 C++03 中类成员名称查找的一部分。在 C++03 中查找将找到 D::X 和 C::x 和 A::x,其中 A::x 匹配,但与 A 类型的两个不同子对象相关联。

在 C++0x 中,对明确子对象的检查现在是各个子条款的一部分,请参阅 DR #39x 直接属于其中的类是一个不明确的基础 - 所以第 5 条将导致编译错误,而不是第 10 条。

请注意,评论谈到了A 的子对象。 A 的一个子对象越过路径BA 的另一个子对象越过路径C。这就是为什么评论说“B::xC::x”。同一类类型的多个子对象的存在可以通过尝试转换为其类类型来确定,忽略可访问性问题:如果转换不明确,则子对象多次出现。

【讨论】:

  • 是的。我记得之前讨论过这个问题。然而这次我的观点是代码示例中的注释是否真的合适。出于某种原因,我觉得 '//ambiguous: B::x or C::x' 是在重载的上下文中,特别是当样本中有两个可见的 'x' 重载时
  • @Chubsdad 该评论没有讨论BC 中的声明,而是讨论了类型A 的子对象的选择。如果你写过d->B::x()d->C::x() 你不会有歧义,因为查找将分别从 BC 开始。
  • 在 C++0x 中,规范更加清晰:有三个明确区分的步骤:1) 查找声明 (10.2) 并进行重载解析。这将找到A::x。 2)检查对象表达式是否(明确)可转换为命名类(in a->c命名类和对象表达式的类型为a,但在a->b::c中,命名类为b)- 11.2/6。并且 3) 检查声明直接是其成员的类是否是命名类的明确基类 - 5.2.5/5。您的代码违反了3)
【解决方案2】:

Clang++ 给出了一些由 g++ 和 Comeau 产生的错误的组合

C:\Users\SUPER USER\Desktop>clang++ chubsdad.cpp
chubsdad.cpp(12) :  error: ambiguous conversion from derived class 'D' to base class
      'A':
    struct D -> struct B -> struct A
    struct D -> struct C -> struct A
   return d->x(); // ambiguous: B::x or C::x
          ^
1 error generated.

【讨论】:

  • 哦,好的。谢谢。我不确定这是否回答了我关于代码 sn-p 中注释背后的适当性和真正意图的问题
  • 我认为ambiguous: B::x or C::x 来自‘A’ is an ambiguous base of ‘D’。所以代码中的注释是正确的恕我直言。
猜你喜欢
  • 2019-12-16
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
相关资源
最近更新 更多