You need template keyword
template<class TA> template<class TBA> struct A<TA>::B : C<typename D<TA>::template T<TBA> > { int foo; };
GCC is correct to give a diagnosis here. This is due to the fact that T cannot be found in the dependent region D<TA> . The value < after it depends on whether T template or not. The standard says that T is not considered a pattern, and therefore T cannot be followed by a list of arguments to the pattern.
template is similar to typename in that it tells the compiler to treat T as a template and that < is the beginning of the argument list anyway. The standard says in paragraphs 14.2/2 and 14.2/4
In order for the template name to be explicitly specified by the template arguments, the name must be known in order to refer to the template.
When then the member template specification appears. or β in the postfix expression or after the nested qualifier name in identified-id, and the postfix expression or qualified box explicitly depends on the template parameter (14.6.2), the member template name must be prefixed with the keyword template. Otherwise, it is assumed that the name is called a non-pattern.
In your case, you have T after the nested qualifier D<TA> , which depends on the template parameter TA . For proper typename-specifier analysis, the constructor D<TA>::T<TBA> must interpret T as the name of a class template that 14.2 forbids.
It is always useful to try and compile with Clang in this thread.
main1.cpp:21:37: error: use 'template' keyword to treat 'T' as a dependent template name struct A<TA>::B : C<typename D<TA>::T<TBA> > ^ template 1 error generated.
Johannes Schaub - litb
source share