Короткий вариант, который вам нужно сделать typename X::Y
всякий раз, когда X зависит или зависит от параметра шаблона. Пока X не будет известен, компилятор не может определить, является ли Y типом или значением. Поэтому вы должны добавить typename
, чтобы указать, что это тип.
Например:
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`
};
Как указывает SBI в комментарии, причиной неоднозначности является то, что Y
может быть статическим членом, перечисление или функции. Не зная тип X
, мы не можем сказать. Стандарт указывает, что компилятор должен считать, что это значение, если оно явно не обозначено типом, используя ключевое слово typename
.
И это походит на комментаторах действительно хотят, чтобы я упомянуть еще один, связанный случай, а также:;)
Если зависимое имя шаблон члена функции, и вы называете это с явным аргументом шаблона (foo.bar<int>()
, для пример), вы должны добавить ключевое слово template
перед именем функции, как в foo.template bar<int>()
.
Причина этого заключается в том, что без ключевого слова шаблона компилятор предполагает, что значение bar
является значением, и вы хотите вызвать меньше, чем оператор (operator<
).
Рекомендую ознакомиться с шаблоном faq: http://womble.decadentplace.org.uk/c++/template-faq.html –