Die kurze Version, die Sie tun müssen, typename X::Y
immer wenn X ist oder hängt von einem Vorlagenparameter ab. Bis X bekannt ist, kann der Compiler nicht feststellen, ob Y ein Typ oder ein Wert ist. Sie müssen typename
hinzufügen, um anzugeben, dass es sich um einen Typ handelt.
Zum Beispiel:
template <typename T>
struct Foo {
typename T::some_type x; // T is a template parameter. `some_type` may or may not exist depending on what type T is.
};
template <typename T>
struct Foo {
typename some_template<T>::some_type x; // `some_template` may or may not have a `some_type` member, depending on which specialization is used when it is instantiated for type `T`
};
Wie sbi in den Kommentaren weist darauf hin, die Ursache der Mehrdeutigkeit ist, dass Y
könnte ein statisches Element, eine Enumeration oder eine Funktion sein. Ohne den Typ von X
zu kennen, können wir nicht sagen. Der Standard gibt an, dass der Compiler davon ausgehen sollte, dass es sich um einen Wert handelt, es sei denn, er ist explizit mit dem Schlüsselwort typename
als Typ gekennzeichnet.
Und es klingt wie die commen will, dass mir wirklich auch anderen verwandten Fall erwähnen:;)
Wenn der abhängige Name ein Funktionselement Vorlage ist, und rufen Sie es mit einem expliziten Template-Argumente (foo.bar<int>()
, für Beispiel), müssen Sie das Schlüsselwort template
vor dem Funktionsnamen hinzufügen, wie in foo.template bar<int>()
.
Der Grund dafür ist, dass der Compiler ohne das Schlüsselwort template davon ausgeht, dass bar
ein Wert ist, und Sie den weniger als Operator (operator<
) darauf aufrufen möchten.
Ich empfehle Ihnen, die Vorlage faq zu lesen: http://womble.decadentplace.org.uk/c++/template-faq.html –