Оба gcc 5.0 и clang 3.6 требуют ключевое слово typename
в следующем примере:
template<int n>
struct I
{
typedef int Type;
};
template<typename T>
struct A
{
int m;
void f()
{
typedef typename I<sizeof m>::Type Type; // typename required
}
};
Это соответствует следующей формулировке в стандарте С++ 11:
[temp.dep.type]/8
Тип зависит, если он
- простой шаблон-идентификатор, в котором либо имя шаблона является параметром шаблона, либо любым шаблоном аргументы - зависимый тип или выражение, зависящее от типа или зависящее от стоимости
Так что I<sizeof m>
зависит, если sizeof m
зависит от значения.
[temp.dep.expr]/4
Выражения следующих форм никогда не зависят от типа (поскольку тип выражения не может быть зависимый):
sizeof unary-expression
[temp.dep.constexpr]/2
Выражения следующей формы зависят от стоимости, если унитарное выражение или выражение являются независимыми или идентификатор типа зависит:
sizeof unary-expression
Итак, sizeof m
зависит только от m
.
[expr.prim.general]/8
Внутри определение нестатической функции-члена, идентификатор, который называет нестатический элемент, преобразуется в выражение доступа к члену класса
So m
является членом в выражении доступа к члену класса.
[temp.dep.type]/4
Имя является членом текущего экземпляра, если оно
- Идентификатор, обозначающий член в выражении доступа к члену класса (5.2.5), для которого тип выражения объекта является текущим экземпляром и id-выражением при поиске (3.4.5), относится, по меньшей мере, к одному члену текущего экземпляра или его независимого базового класса.
Итак, кажется, что m
является членом текущего экземпляра.
[temp.dep.type]/5
Имя является членом неизвестной специализации, если оно
Идентификатор, обозначающий член в выражении доступа к члену класса (5.2.5), в котором либо
тип выражения объекта является текущим экземпляром, текущий экземпляр имеет как минимум один зависимый базовый класс и поиск имени id-выражения не находит члена текущий экземпляр или его независимый базовый класс; или
тип выражения объекта зависит и не является текущим экземпляром.
Итак, m
НЕ является членом неизвестной специализации - он будет найден по имени, чтобы быть членом текущего экземпляра.
[temp.dep.expr]/3
Идентификатор id зависит от типа, если он содержит
- идентификатор, связанный с поиском имени с одной или несколькими объявлениями, объявленными с зависимым типом,
- спецификатор вложенного имени или квалифицированный идентификатор, который называет члена неизвестной специализации
Так как m
имеет тип int
и не является членом неизвестной специализации, ни одна из этих маркеров не сделает id-выражение m
зависимым.
[temp.dep.expr]/5
Выражение доступа к члену класса (5.2.5) зависит от типа, если выражение относится к члену текущего экземпляр и тип ссылочного элемента зависят или выражение доступа к члену класса относится к члену неизвестной специализации.
Когда m
преобразуется в выражение доступа к члену класса, оно все еще не зависит от него, поскольку оно не относится к члену неизвестной специализации.
Должен ли m
считаться зависимым? В отношении соответствующей заметки, следует ли this->m
считать зависимым? Что насчет std::declval<A>().m
?
ИЗМЕНИТЬ
И, наконец, должен ли &A::m
быть зависимым?