class a::b
- подробный спецификатор типа. Поиск имени для разработанного спецификатора типа игнорирует не типовые имена. Поэтому, если вы анализируете шаблон, вы можете предположить две вещи:
- Когда мы создаем экземпляр и выполняем поиск по имени для
b
, либо поиск по имени дает нам тип, либо он выдает ошибку (не найдет никакого имени).
По этой причине в C ++ 0x class a::b
не требуется typename
(вы нигде не можете поместить его в разработанный спецификатор типа). C ++ 03 не позволяет этого, поэтому GCC, по-видимому, реализует правила C ++ 0x как расширение.
Это не особенно плохо. Каждый реальный компилятор реализует правила, которые разумны и просты для реализации в их версии C ++ 03, от их имени, даже если формально они должны будут отклонить его. Тем не менее, class a::b
должен найти имя класса. Если это просто определение типа, то поиск для разработанного спецификатора типа недопустим.
Обратите внимание, что class a::b
- это единственный способ игнорировать не типовые имена в поиске (за исключением непонятных случаев, как до ::
в квалифицированном имени, которые имеют подобные специальные правила). Например
template<typename T>
struct A { typename T::type t; }
struct B { class type { }; int type; };
// invalid, even though GCC accepts that incorrectly
A<B> a;
Если вы компилируете в C ++ 0x и используете class T::type t;
, код становится действительным, потому что class T::type
игнорирует член данных, но находит вложенный класс.