Whether typename T::Before
is valid is not explicitly said by the spec. It is subject of a defect report (because the Standard can very reasonably be read to forbid it): http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287 .
Whether typename T::After
is invalid can also very reasonably be read to be true by the spec, and actually it makes quite a bit of sense (and aforementioned DR still keeps it ill-formed). Because you have an instantiation of a class A<Foo>
, which references another class A<Bar>
during a period where a member Baz
has not yet been declared, and that makes a reference back to A<Foo>::Bar
. That is ill-formed in the case of non-templates aswell (try to “forget” for a moment that you are dealing with templates: surely the lookup of B<A>::After
is done after the A
template was completely parsed, but not after the specific instantiation of it was completely created. And it is the instantiation of it that actually will do the reference!).
struct A {
typedef int Foo;
typedef A::Foo Bar; // valid
typedef A::Baz Lulz; // *not* valid
typedef int Baz;
};