Является ли в качестве шаблона шаблоном `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'

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

Ответы