Действительно ли необходимо средство устранения неоднозначности `typename` в шаблонах классов?

Я уже привык к обязательному использованию 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'

Еще один убедительный случай (по крайней мере, для меня) — это использование typedefs для псевдонимов зависимых типов. В этом случае нет никаких сомнений в том, что все, что следует за ключевым словом 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, можно определить только при создании экземпляра, но это не меняет того факта, что он должен быть типом. Синтаксис просто требует этого, так зачем устранять неоднозначность?


person JorenHeit    schedule 13.01.2015    source источник
comment
На данный момент у вас могут быть специализации, неизвестные компилятору. Также см. это   -  person quantdev    schedule 13.01.2015
comment
В этом ответе обсуждается именно то, что вы спрашиваете.   -  person Baum mit Augen    schedule 13.01.2015
comment
Стоит подчеркнуть или при использовании имени базового класса. То есть template <typename T> struct A : T::x {}; прекрасно компилируется.   -  person rodrigo    schedule 13.01.2015
comment
@quantdev: верно, но не относится к вопросу о том, почему typename требуется даже в контексте, где разрешено только имя типа. (Предположительно ответ заключается в том, что попытка перечислить все случаи, когда требуется избежать двусмысленности, сделает грамматику ужасно сложной по сравнению с простым требованием ее для всех зависимых областей. Но я понятия не имею, является ли это реальной мотивацией для этого правила. .)   -  person Mike Seymour    schedule 13.01.2015
comment
@MikeSeymour То, что вы полагаете, звучит разумно, если бы не то, что это, кажется, уже реализовано в значительной степени (иначе ошибки не выдавались бы так подробно).   -  person JorenHeit    schedule 13.01.2015
comment
@JorenHeit: Одно дело, когда некоторые компиляторы решают реализовать (возможно, довольно сложную) диагностику для некоторых случаев. Другое дело, когда язык требует его от всех компиляторов и пытается перечислить все случаи (и только те случаи), где это требуется. (Кроме того, с точки зрения пользователя, я бы обнаружил, что простому правилу всегда использовать typename, если есть зависимая область, легче следовать, чем выяснить, может ли быть двусмысленность, и использовать typename только в этих случаях, независимо от того, насколько легко или трудно это делает работу реализатора).   -  person Mike Seymour    schedule 13.01.2015
comment
@MikeSeymour Хм, может быть ... У меня мало опыта работы с парсерами и компиляторами, поэтому я не могу судить о влиянии требования этого к реализации. Однако с точки зрения пользователя я бы предпочел не использовать typename везде... это загромождает код и усложняет синтаксис. На самом деле двусмысленная ситуация кажется скорее исключением, чем правилом в моем опыте.   -  person JorenHeit    schedule 13.01.2015
comment
@BaummitAugen Пожалуйста, просветите меня и скажите, почему это дубликат. Вы видели мою правку? Я что-то пропустил?   -  person JorenHeit    schedule 13.01.2015
comment
@JorenHeit Если вам нужны разъяснения по другому ответу на этом сайте, почему бы не оставить комментарий здесь, чтобы автор (или кто-то другой) мог уточнить при редактировании. Ваша проблема определенно рассматривается в этом вопросе, и несовершенные ответы не являются причиной для нового вопроса, а являются наградой или обновлением исходного вопроса.   -  person Baum mit Augen    schedule 13.01.2015
comment
@BaummitAugen За исключением того, что вопрос, на который вы ссылаетесь, явно не спрашивает, что я хочу знать. Во всяком случае, я должен назначить награду за вопрос, который я связал с собой, и даже этот вопрос формулируется не так, как мне хотелось бы.   -  person JorenHeit    schedule 13.01.2015