C++0x 与 using 声明的混淆

标签 c++ c++11 overload-resolution using-declaration

这种情况应该怎么办:

struct A {
  void f();
};

struct B : virtual A {
  using A::f;
};

struct C : virtual A {
  using A::f;
};

struct D : B, C { 
  void g() {
    f();
  }
};

感兴趣的行是f()。显然根据FDIS的10.2查找f成功,找到A::f。但是,重载决议会考虑哪些候选人?规范在 13.3.1p4 中说:

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.

这样做的目的是,对于单个类,如果此类包含自己的成员函数和将基类函数的名称带入作用域的 using 声明,则在重载决策期间,所有候选函数都具有相同的类类型它们的隐含对象参数。但这对上面的例子意味着什么?候选人会是以下吗?

void F1(B&)
void F2(C&)
// call arguments: (lvalue D)

这似乎是错误的,因为根据10.2p7,我们在查找结果集中只有一个声明。我们该如何解释?

最佳答案

我认为由于从 10.2/7 产生的查找集只产生一个声明,因此根本不存在函数重载。 13.3.1/4 仅适用于/如果从 10.2/7 产生的查找集包含两个或更多声明。

编辑:也许我没有我希望的那么清楚。即使 fA 中被重载,我认为大多数相同的推理都适用。也许最好一步一步来。 (注意,在这种情况下,我使用与标准相同的 S(f, X) 表示法,但由于您的派生类最多的是 D,因此您的 S(f, D) 对应于它们的 S(f, C) ,并且您的 S(f, B) 和 S(f, C) 对应于它的 S(f, B1) 和 S(f, B2)。

首先 s(f, D) 是空的,因为我们没有直接在 D 中包含 f 的声明。基于此,我们得到 10.2/5。

在 10.2/6 中,我们首先将 s(f, B) 合并到 S(f, D) 中。由于 s(f, D) 当前为空,我们遵循第一个要点下的第二个条件,S(f, D) 成为 S(f, B) 的拷贝。

然后我们必须将 S(f, C) 合并到 S(f, D) 中。在这种情况下,S(f, C) 的每个子对象成员都是 S(f, D) 的子对象成员。这样就满足了第一个要点的第一个条件,所以我们保持S(f, D)不变,合并就完成了。

此时,不再需要考虑基类 Bi,因此我们的 S(f, D) = S(f, B)。 没有来自 S(f, C) 的声明出现在最终的重载集中根本

然后,如果 S(f, B) 包含两个或更多函数,我们继续 13.3.1,并解决重载集 - 但由于整个集来自 B,问题中提出的情况根本不不存在。

关于C++0x 与 using 声明的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5683687/

相关文章:

c++ - 片段着色器中的“错误 : sampler arrays indexed with non-constant expressions are forbidden in GLSL 1. 30 及更高版本”

c++ - 我的程序没有从文件 :/输出任何内容

c++ - 如何确保使用移动构造函数

C++ 重载解析查询

c++ - 在 C++ 中使用重载的歧义错误

c++ - Eigen - 级联矩阵作为引用

c++ - Cmake 奇怪的错误 : Syntax Error Unexpected Token ('

c++ - 从仿函数模板参数推导出可变参数和返回类型(MSVC 特定)

c++ - 将矩阵旋转 N 度

c++ - 为什么成员函数的重载决议不包括全局函数?