C++类成员名称查找问题(关于标准 n3225 的措辞)
我对标准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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于 B1::* 情况,解释是明确的,只是从 B1 的开头到 i 的偏移量。
在 5.3.1/3 中:
所以技巧是首先让 &D::i 的类型为 B1::* 。那么:
很简单。然后兴趣就来了:
这里的 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:
So the trick is to make &D::i be of type B1::* in the first place. Then:
is simple. The interest then comes in:
Here the RHS is of type B1::* and needs a conversion as we need to determine which base is being referred to.
这
是明确的,因为结果被分配给 B 类的
成员指针
。因此,选择哪个
i
并不重要,因为偏移量是相对于 B 成员(而不是父 D 类)的。所以它对你和我来说都是明确的,但我认为编译器无法处理它。
This:
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.
快速检查一下 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.FWIW,我正在复制我对该问题的 usenet 副本的回答:
&D::i
具有类型int B1::*
,并且明确引用 的数据成员i
B1
。如果您使用D
对象取消引用它,或者将其分配给int
,您将根据需要得到歧义。D::*
这些编译器都还没有实现 10.2。
你需要举例说明你不明白的地方。
基于新算法的查找规则解耦了运行时问题(查找一个)
唯一的对象)从编译时/查找问题(找到一个声明,
名称指)。
以下内容采用新的措辞,格式良好:
声明
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:
&D::i
has typeint B1::*
, and unambiguously refers to data memberi
ofB1
. If you dereference it with aD
object or if you assign it to aint
, you will get an ambiguity as needed.D::*
None of those compilers implement 10.2 yet.
You need to give examples that show what you don't understand.
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:
The declaration
using A::x;
introduces a member name into B that refers tothe declaration
Z::z
. In a declarative context, this is perfectly fine. Anerror 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.