【发布时间】:2020-10-04 14:18:35
【问题描述】:
什么时候发生:
- 我在全局范围内声明并定义了一个名称 X(对象或类型)。
- 我开始写一堂课。在类内部,但在函数体等外部,我使用 X。
- 稍后在课堂上,我再次声明名称 X。
在the Class Scope page on cppreference.com 上,这被视为未定义行为。代码 sn-p 如下所示:
typedef int c; // ::c
enum { i = 1 }; // ::i
class X {
char v[i]; // Error: at this point, i refers to ::i
// but there is also X::i
int f() {
return sizeof(c); // OK: X::c, not ::c is in scope inside a member function
}
char c; // X::c
enum { i = 2 }; // X::i
};
typedef char* T;
struct Y {
T a; // Error: at this point, T refers to ::T
// but there is also Y::T
typedef long T;
T b;
};
但是在 Stanley B. Lippman 的书Inside the C++ Object Model的第 3.1 章中,编译器应该会引发错误。
他的cmets:
以下面的代码片段为例,两者中的长度类型 成员函数签名解析为全局 typedef 的签名,即 int。当遇到嵌套类型定义的后续声明时, 标准要求将较早的绑定标记为非法
他的代码 sn-p 是这样的:
typedef int length;
class Point3d {
public:
// oops: length resolves to global
// ok: _val resolves to Point3d::_val
void mumble( length val ) { _val = val; }
length mumble() { return _val; }
private:
// length must be seen before its first reference within the class.
// This declaration makes the prior reference illegal.
typedef float length;
length _val;
};
我用 clang 7.0.0 测试,没有警告或错误,length 似乎绑定到int。我知道编译器测试结果不能用于分析 UB,所以我问这个问题。
谁是对的?或者如果他们都是正确的,我错过了什么?现行标准对此有何规定?
【问题讨论】:
-
不,没有 UB。编译器可以明确地解析所有 typedef 引用。
c甚至没有用作类型 BTW。 -
有些编译器比其他编译器抱怨更多,直播 - godbolt.org/z/s7e4Er
-
该页面上没有任何地方表明这是 UB。格式错误的 NDR 是不同的。不要随意换词!!
-
关于格式错误的 NDR 是否为 UB 的争论,请参阅答案和 cmets here。我会说它把讨论带到了错误的地方......主要问题是代码是否合法,如果不合法,clang 是否有编译它的错误。底线是the code is illegal but clang is ok for compiling it。
-
@AsteroidsWithWings 感谢您指出!我不知道有一个概念叫做 ill-formed NDR,点击链接会跳转到未定义行为的页面,所以我只是假设它们是相同的含义。我的错。
标签: c++ language-lawyer undefined-behavior