I will add to Jesse's answer about the seemingly peculiar behavior of GCC in compiling:
typedef A<T> A;
vs
typedef ::A<T> A;
This also applies to using statements as well of the form:
using A = A<T>;
using A = ::A<T>;
What seems to be happening within GCC, is that during the compilation of the typedef/using statement declaring B::A, that the symbol B::A becomes a valid candidate within the using statement itself. I.e. when saying using A = A<T>;
or typedef A<T> A;
GCC considers both ::A
and B::A
valid candidates for A<T>
.
This seems odd behavior because as your question implies, you don't expect the new alias A to become a valid candidate within the typedef itself, but as Jesse's answer also says, anything declared within a class becomes visible to everything else inside the class - and in this case apparently even the declaration itself. This type of behavior may be implemented this way to permit recursive type definitions.
The solution as you found is to specify for GCC precisely which A you're referring to within the typedef and then it no longer complains.
A
is used before the localA
is declared, this error will occur. That said, any use ofA
(declaring a member) beforetypedef ::A<T> A
; will yield the same error. Moving the declaration below will change theA
to a local one and also fix the error. It's the same with thetypedef A<T> A
, you're using the globalA
before, "on the left" and then redeclaring it immediately "on the right". This is just g++ making sure that all the occurrences ofA
in the class will have the same meaning (not::A
, that doesn't change). – Fatherhood