Я уже привык к обязательному использованию typename
в шаблонах классов, но не могу не задаться вопросом, действительно ли это необходимо. Этот вопрос задавали раньше здесь, на SO, но я не знал не совсем удовлетворен ответами (как и ОП, если я правильно понял).
Параметры когда и где совершенно ясны (из cppreference.com):
В объявлении или определении шаблона, включая шаблон псевдонима, имя, которое не является членом текущего экземпляра и зависит от параметра шаблона, не считается типом, если не используется ключевое слово typename или если оно уже не было устанавливается как имя типа, например. с объявлением typedef или с использованием имени базового класса.
Когда шаблон (класса или функции) определен (еще не создан), я понимаю, что оператор
A::Type *tp;
где A
— параметр типа шаблона, а Type
должен быть вложенным типом, неоднозначно. Type
также может быть статическим членом или значением перечисления или какими-то другими возможностями, о которых я сейчас не могу думать. Оператор *
в этом случае является умножением (при условии, что "умножение" является правильной формулировкой для реализации operator*()
), а не объявлением указателя. Однако я не могу представить себе ситуацию, в которой такой оператор мог бы представлять умножение в области видимости класса. Конечно, в области функций, но что это может означать в области класса, кроме объявления указателя?
Я хочу сказать, что во многих случаях компилятор ожидает имя типа в какой-то момент, но все еще требует от нас, чтобы мы явно указали это, даже если других вариантов нет. Тот факт, что GCC и Clang выдают ошибку, а не предупреждение, довольно показателен:
template <typename T>
struct A
{
T::x *p;
};
GCC: error: need ‘typename’ before ‘T::x’ because ‘T’ is a dependent scope
CLANG: error: missing 'typename' prior to dependent type name 'T::x'
Еще один убедительный случай (по крайней мере, для меня) — это использование typedef
s для псевдонимов зависимых типов. В этом случае нет никаких сомнений в том, что все, что следует за ключевым словом typedef
, должно быть типом (правильно?), так зачем устранять неоднозначность?
Подводя итог: во многих случаях, когда компилятор может легко сделать вывод из синтаксиса и контекста, имеет ли программист в виду тип или переменную, почему необходимо устранять неоднозначность?
ИЗМЕНИТЬ
Комментарии и предлагаемый дубликат упоминают, что специализации могут усложнить ситуацию. Например (взято из ответа в другой теме):
struct B {
typedef int result_type;
};
template<typename T>
struct C { }; // could be specialized!
template<typename T>
struct D : B, C<T> {
void f() {
// OK, member of current instantiation!
// A::result_type is not dependent: int
D::result_type r1;
// error, not a member of the current instantiation
D::questionable_type r2;
// OK for now - relying on C<T> to provide it
// But not a member of the current instantiation
typename D::questionable_type r3;
}
};
Я понимаю, что C
может быть специализированным для T
, и вопрос о том, существует ли C<T>::questionable_type
, можно определить только при создании экземпляра, но это не меняет того факта, что он должен быть типом. Синтаксис просто требует этого, так зачем устранять неоднозначность?
template <typename T> struct A : T::x {};
прекрасно компилируется. - person rodrigo   schedule 13.01.2015typename
требуется даже в контексте, где разрешено только имя типа. (Предположительно ответ заключается в том, что попытка перечислить все случаи, когда требуется избежать двусмысленности, сделает грамматику ужасно сложной по сравнению с простым требованием ее для всех зависимых областей. Но я понятия не имею, является ли это реальной мотивацией для этого правила. .) - person Mike Seymour   schedule 13.01.2015typename
, если есть зависимая область, легче следовать, чем выяснить, может ли быть двусмысленность, и использоватьtypename
только в этих случаях, независимо от того, насколько легко или трудно это делает работу реализатора). - person Mike Seymour   schedule 13.01.2015typename
везде... это загромождает код и усложняет синтаксис. На самом деле двусмысленная ситуация кажется скорее исключением, чем правилом в моем опыте. - person JorenHeit   schedule 13.01.2015