В следующих случаях имя введенного класса обрабатывается как имя шаблона самого шаблона класса:
- это сопровождается <
- используется в качестве аргумента шаблона, соответствующего параметру шаблона
- это последний идентификатор в разработанном спецификаторе класса объявления шаблона класса друга.
Поэтому я попытался изучить все 3 случая (дополнительно в контексте базовой неопределенности, хотя я думаю, что здесь это не должно иметь значения).
Первый случай кажется простым.
Вопрос в том, почему не закомментированные примеры работают? Они не на обоих GCC & Clang, так что я не думаю, что это проблема реализации
template <template <class> class> struct A;
template <class T> struct Base {};
template <class T> struct Derived: Base<int>, Base<char>
{
// #1
typename Derived::Base<double> d;
// #2
// using a = A<Base>;
using a = A<Derived::template Base>;
// #3
template<class U1>
friend struct Base;
// template<class U>
// friend struct Derived::template Base;
};
Правила выше только для самого шаблона, а не для баз? Если да, то каковы правила для баз, особенно для последних 2 случаев?
Соответствующее правило здесь [Temp.local] / 4:
Поиск, который находит имя введенного класса ([class.member.lookup]), может привести к неоднозначности в некоторых случаях (например, если он найден в нескольких базовых классах). Если все найденные имена введенных классов относятся к специализациям одного и того же шаблона класса, и если имя используется как Имя Шаблона, ссылка относится к самому шаблону класса, а не к его специализации, и не является двусмысленной. [ Пример:
template <class T> struct Base { }; template <class T> struct Derived: Base<int>, Base<char> { typename Derived::Base b; // error: ambiguous typename Derived::Base<double> d; // OK };
— конец примера]
Что, я думаю, означает, что это ошибка gcc и clang. В:
using a = A<Base>;
Все найденные имена введенных классов ссылаются на специализации одного и того же шаблона класса (Base<T>
) а также имя используется как Имя Шаблона (потому что это аргумент шаблона для параметра шаблона), так что это должно относиться только к самому шаблону класса, а не быть двусмысленным.
Других решений пока нет …