【问题标题】:Overload Resolution: How is this not ambiguous?重载解决方案:这不是模棱两可的吗?
【发布时间】:2015-12-15 03:06:16
【问题描述】:

假设我们有这段代码,复制自一个单独的问题:

namespace x 
{
    void f()
    {
    }

    class C 
    {
        void f() 
        {
            using x::f;
            f();         // <==
        }
    };
}

指定行上的名称f 明确指代x::f(至少根据gcc 和clang)。为什么在这种情况下x::fx::C::f 更受欢迎?因为两个名字都是可见的,所以不应该模棱两可吗?

【问题讨论】:

    标签: c++ language-lawyer overload-resolution


    【解决方案1】:

    因为using声明将x::f纳入f的范围,比C的范围窄。不合格查找会考虑本地块范围,找到匹配项,然后在考虑更广泛的类范围之前停止。由于没有函数参数,因此没有依赖于参数的查找,因此不考虑进一步的作用域。

    【讨论】:

      【解决方案2】:

      @MikeSeymour 的回答很到位;以下是相关的标准引用(C++11,强调我的):

      13.3.1.1.1/3:

      在不合格的函数调用中,名称不受-&gt;. 运算符的限定,并且具有更通用的形式 primary-expression。 名称在函数调用的上下文中按照正常规则进行查找 用于函数调用 (3.4) 中的名称查找。通过该查找找到的函数声明构成了一组 候选函数。 由于名称查找规则,候选函数集完全由 (1) 非成员函数或 (2) 完全是某个类 T 的成员函数。 ...

      3.4.1/1:

      在 3.4.1 中列出的所有情况下,将按照每个列表中列出的顺序搜索范围以查找声明 各自的类别;一旦找到名称的声明,名称查找就会结束。如果没有声明 发现,程序格式不正确。

      3.4.1/8

      在函数的 declarator-id 之后的类 X 的成员函数 (9.3) 的定义中使用的名称 ... 应在其中之一中声明 有以下几种方式:

      • 在其用于使用它的块或封闭块 (6.3) 之前,或
      • 应为X 类的成员或X (10.2) 基类的成员,或
      • ...

      从 3.4.1/8 开始,我们看到在使用它的块中名称 f 的声明(例如声明 using x::f;)早于 f 作为类 @ 的成员列出987654330@。根据 3.4.1/1,选择较早的那个,因此整个查找解析为 using 声明引入的 x::f

      【讨论】:

        【解决方案3】:

        我认为来自 C++ 标准的这些引用将是相关的:

        来自 C++ 标准(7.3.3 using 声明)

        13 由于 using-declaration 是一个声明,因此限制 同一声明区域中的同名声明 (3.3) 也适用于 using-declarations。

        和(3.3.7 类范围)

        4) 在成员函数中声明的名称隐藏了 范围延伸到或超过成员末尾的同名 函数的类。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多