Вопрос: typename, члены типа и члены non-type: это действительный код?


Рассмотрим следующий код:

struct S {
    struct type {};
    type type;
};

int main() {  
    typename S::type t;
    (void) t;
}

Помимо того, что это далеко не хорошая идея, я экспериментировал, прочитав здесь еще один вопрос о SO.
Я обнаружил, что приведенный выше фрагмент скомпилировано без ошибок GCC  и это отклонено clang 3.9  со следующей ошибкой:

error: typename specifier ссылается на тип типа «тип» не в типе 'в' S '

Я подозреваю, что clang в этом случае прав, и GCC ошибается (на самом деле, я открываю проблему для последнего).
Правильно ли это, или что действительное использование typename?


Примечание. Я не спрашиваю, как это решить, я знаю, как это сделать. Я спрашиваю только, является ли этот код действительным или нет.


3


источник


Ответы:


[Temp.res] / 4 :

Обычное квалифицированное имя поиска используется для поиска Квалифицированный-идентификатор  даже в присутствии typename,

То есть, в отличие от случая с уточненный тип Спецификатор s, поиск имени в этом случае не игнорирует имена, отличные от типа.

[Temp.res] / 3 :

Если Квалифицированный-идентификатор  в имяТипа спецификатор  не обозначает шаблон типа или класса, программа плохо сформирована.

Таким образом, рассматриваемая программа плохо сформирована.

[temp.res] / 4 также имеет пример для этого:

struct A {
  struct X { };
  int X;
};
struct B {
  struct X { };
};
template<class T> void f(T t) {
  typename T::X x;
}
void foo() {
  A a;
  B b;
  f(b);             // OK: T::X refers to B::X
  f(a);             // error: T::X refers to the data member A::X not the struct A::X
}

6