What happens when:
- I declare and define a name X (either object or type) in the global scope.
- I start writing a class. Inside the class, but outside of function bodies etc., I use X.
- Later in the class, I declare name X again.
On the Class Scope page on cppreference.com, this is considered undefined behavior. The code snippet looks like this:
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;
};
But in Chapter 3.1 of Stanley B. Lippman's book Inside the C++ Object Model, the compiler should raise an error.
His comments:
In the following code fragment, for example, the type of length in both member function signatures resolves to that of the global typedef—that is, to int. When the subsequent declaration of the nested typedef of length is encountered, the Standard requires that the earlier bindings be flagged as illegal
His code snippet looks like this:
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;
};
I tested with clang 7.0.0, there is no warning or error, and the length
seems to bind to int
. I understand that compiler testing results cannot be used to analyze UBs, so I'm asking this question.
Who is right? Or if they are both right, what am I missing? What does the current standard say about this?