Почему injected-class-name иногда не рассматривается как имя шаблона в шаблоне класса? - PullRequest
0 голосов
/ 08 мая 2018

Источник

В следующих случаях имя введенного класса обрабатывается как имя шаблона самого шаблона класса:

  • сопровождается <</li>
  • используется в качестве аргумента шаблона, соответствующего параметру шаблона
  • это последний идентификатор в разработанном спецификаторе класса объявления шаблона класса друга.

Поэтому я попытался изучить все 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 случаев?

1 Ответ

0 голосов
/ 08 мая 2018

Соответствующее правило здесь [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>) и , имя используется как имя-шаблона (потому что это аргумент шаблона для параметра шаблона), так что это должно относиться только к самому шаблону класса, а не быть двусмысленным.

...