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

发布于 2024-10-13 02:16:37 字数 1598 浏览 7 评论 0原文

我对标准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 = &D::i; // Unambigious

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/13中的例子应该如何根据10.2/3-10.2/6进行查找? 10.2/13的用意是什么,即10.2/13被视为10.2/3-10.2/6的例外情况是什么?

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


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

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

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

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

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

I am very confused about the standard 10.2/13,

[ Note: Even if the result of name lookup is unambiguous, use of a name found in multiple subobjects might still be ambiguous (4.11, 5.2.5, 5.3.1, 11.2).—end note ] [ Example:

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

I cannot see why this is unambiguous int B1::* mpB1 = &D::i; // Unambiguous

Visual C++, Gcc and CLang all say that it is ambiguous access to D::i!

The wording seems to be related to the core issue #39
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#39, and the final proposal is here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf

I now find that the new algorithm-based wordings (10.2/3-10.2/6) are even more confusing because none of the note in 10.2/9, 10.2/10, 10.2/11, and 10.2/13 fully complies to 10.2/3-10.2/6. I can take 10.2/9-10.2/11 as exceptions, but I am especially confused about 10.2/13. I have no idea on the intention of 10.2/13.

How should the example in 10.2/13 be looked-up according to the 10.2/3-10.2/6? What's the intention of 10.2/13, i.e., what's the situation that 10.2/13 is considered as an exception of 10.2/3-10.2/6?

Please give me some hints. Thank you very much.


After some thinking, I think the intention of 10.2/13 is clearer to me.

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

This should be unambiguous and the current compilers are wrong on this. This is unambiguous because pointer to class members initialization doesn't involve in accessing the object yet.

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

This actually means when convert from int B1::*mpB1 to int D::*mpD, the conversion is ambiguous due to ambiguous base classes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黑色毁心梦 2024-10-20 02:16:37

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

在 5.3.1/3 中:

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

所以技巧是首先让 &D::i 的类型为 B1::* 。那么:

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

很简单。然后兴趣就来了:

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

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

For the B1::* case, the interpretation is unambiguous, simply being the offset from the start of B1 to i.

In 5.3.1/3:

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

So the trick is to make &D::i be of type B1::* in the first place. Then:

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

is simple. The interest then comes in:

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

Here the RHS is of type B1::* and needs a conversion as we need to determine which base is being referred to.

梦境 2024-10-20 02:16:37

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

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

所以它对你和我来说都是明确的,但我认为编译器无法处理它。

This:

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

Is unambiguous because the result is being assigned to a pointer to member of class B.
So it don't matter which i is chosen as the offset is relative to a B member (not the parent D class).

So it is unambiguous to you and me but I don't think the compiler can handle it.

雾里花 2024-10-20 02:16:37

快速检查一下 ISO IEC 14882 2003 第 10 节,没有此示例或类似的内容。 C++0x 是草案标准,VC++/GCC/CLang 不符合它。

我的猜测:这是新的自动输入的一些副产品,在旧的 C++ 标准中找不到。

A quick check on ISO IEC 14882 2003 Section 10 does not have this example, or anything similar to this. C++0x is draft standard, and VC++/GCC/CLang are not compliant to it.

My Guess: This is some byproduct of the new auto typing and not found in older C++ standard.

挖鼻大婶 2024-10-20 02:16:37

FWIW,我正在复制我对该问题的 usenet 副本的回答:

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

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 = &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)。

不要因为在成员指针的情况下犯了这样的错误而感到难过。 我过去也这样做过,相应的问题报告实际上已经变成了 C+ +0x 草稿。幸运的是,当他们注意到这一点时,将其改回改变是错误的。

FWIW, I'm copying over my answer I gave to the usenet copy of this question:

Hi all,

I am very confused about the standard n3225 10.2/13,
 
[ Note: Even if the result of name lookup is unambiguous, use of a
name found in multiple subobjects might still be ambiguous (4.11,
5.2.5, 5.3.1, 11.2).—end note ] [ Example:  

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

I cannot see why this is unambiguous int B1::* mpB1 = &D::i; //
Unambiguous  

&D::i has type int B1::*, and unambiguously refers to data member i of
B1. If you dereference it with a D object or if you assign it to a int
D::*
, you will get an ambiguity as needed. 

Visual C++, Gcc and CLang all say that it is ambiguous access to D::i!  

None of those compilers implement 10.2 yet. 

The wording seems to be related to the core issue #39
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#39, and
the final proposal is here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf

I now find that the new algorithm-based wordings (10.2/3-10.2/6) are
even more confusing because none of the note in 10.2/9, 10.2/10,
10.2/11, and 10.2/13 fully complies with 10.2/3-10.2/6. I can take
10.2/9-10.2/11 as exceptions, but I am especially confused about
10.2/13. I have no idea on the intention of 10.2/13.  

You need to give examples that show what you don't understand. 

How should the example in 10.2/13 be looked-up according to the
10.2/3-10.2/6? What's the intention of 10.2/13, i.e., what's the
situation of which 10.2/13 is considered as an exception of
10.2/3-10.2/6?  

The new algorithm based lookup rules decouples runtime concerns (finding an
unique object) from compile time/lookup concerns (finding a declaration that
a name refers to). 

The following is well-formed with the new wording:

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

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

The declaration using A::x; introduces a member name into B that refers to
the declaration Z::z. In a declarative context, this is perfectly fine. An
error is risen only when you access B::z as a member access expression
(5.2.5). 

Don't feel bad about having mistaken this about the member pointer case. I did so too in the past, and the corresponding issue report actually made it into a C++0x draft. They luckily changed it back when they noticed that change was wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文