Ответ 1
Мой первый инстинкт - сказать, что VС++ прав в этом. Поиск имени A
в B
должен найти inted-class-name A
внутри A<T>
, который также может использоваться как имя типа для ссылки на A<T>
.
С++ 11 [temp.local]:
1 Подобно нормальным (не шаблонным) классам, шаблоны классов имеют введенное имя класса (раздел 9). Имя введенного класса может использоваться как имя шаблона или имя типа. Когда он используется с шаблоном-аргументом-списком, в качестве аргумента-шаблона для шаблона-шаблона шаблона или в качестве конечного идентификатора в специфицированном спецификаторе типа объявления шаблона класса друга, оно относится к самому шаблону класса. В противном случае это эквивалентно к имени шаблона, за которым следуют шаблонные параметры шаблона класса, заключенного в
<>
.2...
3 Введенное имя класса шаблона класса или специализации шаблона шаблона можно использовать либо как имя шаблона или имя типа, где бы оно ни находилось. [Пример:
template <class T> struct Base { Base* p; }; template <class T> struct Derived: public Base<T> { typename Derived::Base* p; // meaning Derived::Base<T> };
Однако в то же время [temp.dep] §3 гласит:
3 В определении шаблона класса или класса, если базовый класс зависит от шаблона-параметра, базовый класс область не рассматривается при поиске неквалифицированного имени либо в точке определения шаблона класса или член или во время создания шаблона или члена класса.
Исходя из этого, я бы более склонен сказать, что clang на самом деле прав, поскольку имя введенного класса A
находится внутри области A<T>
, которая зависит от параметра шаблона B
T
и, таким образом, не выполняется поиск при неквалифицированном поиске имени. Вторичными доказательствами для этого было бы то, что в примере из [temp.local] вместо Base
используется Derived::Base
.
Итак, я бы сказал, что
-
это хороший угловой регистр, а
-
clang на самом деле прав, чтобы не исследовать область действия
A<T>