The OP writes in the comment section:
... My question is wether [sic] it is legal to redefine a type name before it has been used in a class.
The answer is yes. It is legal to define a type name in a class that shadows a type name in an enclosing scope. What is not allowed is the following:
- A name, call it
T (though it need not be a type), is used inside a class, and name lookup finds some declaration D, and
- The class declares a member named
T, and
- After the class has been completely defined, if the compiler goes back and parses the previous use of the name
T, it now finds the new member declaration instead of D.
Let's go over a few examples to clarify the issue.
using T = X;
class C {
using T = Y;
T x;
};
The above example is legal because when the compiler sees T x;, it has already seen using T = Y;, so T can only resolve to Y. There are no subsequent declarations inside the class that can change the meaning later.
using T = X;
class C {
T x;
using T = Y;
};
The above example is illegal. The compiler at first looks up T and finds the enclosing definition of T as X, since C::T hasn't been declared yet. But after C::T has been declared, it implies that if T x; were to be reinterpreted, then T would now refer to C::T instead, since the class scope takes precedence over the enclosing scope.
using T = ::X;
class C {
T x;
using T = ::X;
};
The above example is illegal. The fact that both declarations of T make it refer to the same type is not relevant. The violation occurs because T x; would find a different declaration of T after the class is completely defined.
using T = X;
class C {
::T x;
using T = Y;
};
The above example is legal. The declaration using T = Y; does not change the meaning of ::T, because ::T will always refer to the global declaration even though C::T is there.
using T = X;
class C {
void foo() { T x; }
using T = Y;
};
The above example is legal. The body of foo is a complete-class context, which implies that name lookup for T is not done until after the entire class has been seen. Put another way, the declaration using T = Y; in a sense always "precedes" the body of foo so this is similar to the first example.