C ++类成员名称查找问题(关于标准n3225的措辞)

时间:2011-01-20 01:49:10

标签: c++ c++11 name-lookup

我对标准10.2 / 13非常困惑,

  

[注意:即使名称查找的结果是明确的,使用在多个子对象中找到的名称可能仍然不明确(4.11,5.2.5,5.3.1,11.2).- end note] [示例:< / p>

struct B1 {
  void f();
  static void f(int);
  int i;
};
struct B2 {
  void f(double);
};
struct I1: B1 { };
struct I2: B1 { };
struct D: I1, I2, B2 {
  using B1::f;
  using B2::f;
  void g() {
    f(); // Ambiguous conversion of this
    f(0); // Unambiguous (static)
    f(0.0); // Unambiguous (only one B2)
    int B1::* mpB1 = &D::i; // Unambiguous
    int D::* mpD = &D::i; // Ambiguous conversion
  }
};

我不明白为什么这是明确的int B1 :: * mpB1 =&amp; D :: i; //明确无误

Visual C ++,Gcc和CLang都说这是对D :: i的模糊访问!

措辞似乎与核心问题#39有关 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#39,最终提案在此处:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf

我现在发现新的基于算法的措辞(10.2 / 3-10.2 / 6)更令人困惑,因为10.2 / 9,10.2 / 10,10.2 / 11和10.2 / 13中的注释都没有完全符合至10.2 / 3-10.2 / 6。我可以将10.2 / 9-10.2 / 11作为例外,但我对10.2 / 13特别困惑。我不知道10.2 / 13的意图。

如何根据10.2 / 3-10.2 / 6查找10.2 / 13中的示例? 10.2 / 13的意图是什么,即10.2 / 13被视为10.2 / 3-10.2 / 6例外的情况是什么?

请给我一些提示。非常感谢你。


经过一番思考,我认为10.2 / 13的意图对我来说更清楚。

int B1 :: * mpB1 =&amp; D :: i; //明确无误

这应该是明确的,目前的编译器在这方面是错误的。这是明确的,因为指向类成员初始化的指针不涉及访问对象。

int D :: * mpD =&amp; D :: i; //不明确的转换

这实际上意味着当从int B1 :: * mpB1转换为int D :: * mpD时,由于基类不明确,转换是不明确的。

4 个答案:

答案 0 :(得分:4)

对于B1 :: *情况,解释是明确的,只是从B1的开始到i的偏移。

在5.3.1 / 3中:

struct A { int i; };
struct B : A { };
... &B::i ... // has type int A::*

所以诀窍是让&amp; D :: i首先成为B1 :: *类型。然后:

int B1::* mpB1 = &D::i; // Unambiguous

很简单。然后兴趣出现:

int D::* mpD = &D::i; // Ambiguous conversion

这里RHS是B1 :: *类型,需要转换,因为我们需要确定引用哪个基数。

答案 1 :(得分:2)

此:

int B1::* mpB1 = &D::i; // Unambiguous

是明确的,因为结果被分配给了班级的pointer to member 因此,选择哪个i并不重要,因为偏移量是相对于B成员(而不是父D类)。

所以这对你我来说是明确的,但我不认为编译器可以处理它。

答案 2 :(得分:0)

快速检查ISO IEC 14882 2003第10节没有这个例子或类似的东西。 C ++ 0x是 draft 标准,VC ++ / GCC / CLang不符合它。

我的猜测:这是新auto打字的副产品,在较旧的C ++标准中找不到。

答案 3 :(得分:0)

FWIW,我正在复制我给这个问题的usenet副本的答案:

  

大家好,
  
  我对标准的n3225 10.2 / 13非常困惑,   
  [注意:即使名称查找的结果是明确的,使用a   在多个子对象中找到的名称可能仍然不明确(4.11,   5.2.5,5.3.1,11.2).- end note] [示例:   

struct B1 {
  void f();
  static void f(int);
  int i;
};
struct B2 {
  void f(double);
};
struct I1: B1 { };
struct I2: B1 { };
struct D: I1, I2, B2 {
  using B1::f;
  using B2::f;
  void g() {
    f(); // Ambiguous conversion of this
    f(0); // Unambiguous (static)
    f(0.0); // Unambiguous (only one B2)
    int B1::* mpB1 = &D::i; // Unambiguous
    int D::* mpD = &D::i; // Ambiguous conversion
  }
};
  

我不明白为什么这是明确的int B1 :: * mpB1 =&amp; D :: i; //   明确的   

&D::i的类型为int B1::*,并且明确指的是数据成员i B1。如果您使用D对象取消引用它,或者将其分配给int  D::*,则会根据需要产生歧义。

  

Visual C ++,Gcc和CLang都说它是对D :: i的模糊访问!   

这些编译器都没有实现10.2。

  

措辞似乎与核心问题#39有关   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#39,和   最终提案在这里:   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf      我现在发现新的基于算法的措辞(10.2 / 3-10.2 / 6)是   更令人困惑的是因为10.2 / 9,10.2 / 10中的注释都没有,   10.2 / 11和10.2 / 13完全符合10.2 / 3-10.2 / 6。我可以做   10.2 / 9-10.2 / 11作为例外,但我特别困惑   10.2 / 13。我不知道10.2 / 13的意图。   

您需要举例说明您不理解的内容。

  

应如何根据以下内容查找10.2 / 13中的示例   10.2 / 3-10.2 / 6?什么是10.2 / 13的意图,即什么是   其中10.2 / 13的情况被视为例外情况   10.2 / 3-10.2 / 6?   

基于新算法的查找规则解耦了运行时问题(找到一个 来自编译时/查找问题的唯一对象(找到一个声明 一个名字指的是)。

以下是新措词的良好形式:

struct Z { int z; };
struct X : Z { };
struct Y : Z { };
struct A : X, Y { };

struct B : A {
  using A::z;
};

声明using A::x;在B引用的成员名称中引入 宣言Z::z。在声明性语境中,这非常好。一个 仅当您将B::z作为成员访问表达式访问时,错误才会升级 (5.2.5)。

关于成员指针案例的错误,不要感到难过。过去I did so too,相应的issue report实际上已将其变为C ++ 0x草案。幸运的是changed it back当他们注意到变化是错误的时候。