From unqualified names:
For a name used anywhere in class definition (including base class specifiers and nested class definitions), except inside a member function body, a default argument of a member function, exception specification of a member function, or default member initializer, where the member may belong to a nested class whose definition is in the body of the enclosing class, the following scopes are searched:
- the body of the class in which the name is used until the point of use
(emphasis mine)
Now let us apply this to the two cases.
Case 1
Here we consider:
namespace ns2 {
//-------------------v---------->#1
struct B : ns1::A< A, B> {
//------------------v----------->#2
typedef ns1::A< A, B> Bar;
};
}
In this case, the unqualified name A at point #1 is looked up and according to bullet point 1 quoted above, it refers to ns2::A.
Now, the base class of B is ns1::A< ns2::A, ns2::B> and this base class has an injected-class name A which refers to the current instantiation ns1::A< ns2::A, ns2::B>. Moreover, it is as-if this base class has a public member named A referring to ns1::A< ns2::A, ns2::B>.
This means that the derived class B behaves as-if it has an inherited member named A from the base class.
Now, the A at point #2 is looked up and since this derived class B has inherited a member named A(same as ns1::A) from the base class, the bullet point 1 founds this ns1::A(which itself refers to ns1::A< ns2::A, ns2::B>). This also explains why in your posted image the type of A at point #2 is ns1::A< ns2::A, ns2::B>.
Case 2
Here we consider:
namespace ns2 {
//-------------------------------v------> #1
struct /*ns2*/ A : ns1::A<int, A> {
//----------------------v---------------> #2
typedef ns1::A<int, A> Foo;
};
}
At point #1, according to bullet point 1, A is refers to ns2::A just like in case 1 discussed before.
But this time the inherited member named A from base class ns1::A<int, ns2::A> is hidden by a member with the same name. This is because the class ns2::A itself has an injected-class name A so it is as-if it has a member named A which will hide the inherited member with the same name from the base.
This in turn means that the A at point #2 refers to ns2::A(unlike in case 1).