«Квалифицированный» означает, что он находится не в той же области, а в текущей области, которая также зависит от шаблона.Например,
template <class T> struct C {
typedef int b;
}
b
является квалифицированным id
при ссылке в другом шаблоне, например,
template<typename T> struct M {
typename C<T>::b bb;
}
Соответствующая цитата из стандарта (§14.6.3):
Квалифицированному идентификатору, который относится к типу и в котором спецификатор вложенного имени зависит от параметра шаблона (14.6.2), должен предшествовать ключевое слово typename, чтобы указать, что квалифицированный идентификаторобозначает тип, образуя подробный спецификатор типа (7.1.5.3).
И §14.6.2:
A name used in a template declaration or definition and that is dependent on a template-parameter is
assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified
by the keyword typename. [Example:
// no B declared here
class X;
template<class T> class Y {
class Z; // forward declaration of member class
void f() {
X* a1; // declare pointer to X
T* a2; // declare pointer to T
Y* a3; // declare pointer to Y<T>
Z* a4; // declare pointer to Z
typedef typename T::A TA;
TA* a5; // declare pointer to T’s A
typename T::A* a6; // declare pointer to T’s A
T::A* a7; // T::A is not a type name:
// multiply T::A by a7; ill-formed,
// no visible declaration of a7
B* a8; // B is not a type name:
// multiply B by a8; ill-formed,
// no visible declarations of B and a8
}
};
—end example]
И §14.6.7:
Within the definition of a class template or within the definition of a member of a class template, the keyword
typename is not required when referring to the unqualified name of a previously declared member
of the class template that declares a type. The keyword typename shall always be specified when the
member is referred to using a qualified name, even if the qualifier is simply the class template name.
[Example:
template<class T> struct A {
typedef int B;
A::B b; // ill-formed: typename required before A::B
void f(A<T>::B); // ill-formed: typename required before A<T>::B
typename A::B g(); // OK
};
The keyword typename is required whether the qualified name is A or A<T> because A or A<T> are synonyms
within a class template with the parameter list <T>. ]