g++ is correct and conforming to the standard. From [3.3.7/1]:
A name N used in a class S shall refer to the same declaration in its
context and when re-evaluated in the completed scope of S. No
diagnostic is required for a violation of this rule.
Before the typedef, A
referred to the ::A
, however by using the typedef, you now make A
refer to the typedef which is prohibited. However, since no diagnostic is required
, clang is also standard conforming.
jogojapan's comment explains the reason for this rule.
Take the following change to your code:
template<class T>
class A
{};
template<class T>
class B
{
public:
A a; // <-- What "A" is this referring to?
typedef A<T> A;
};
Because of how class scope works, A a;
becomes ambiguous.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…