Ключевое слово шаблона для устранения неоднозначности для элемента шаблона: когда именно? - PullRequest
2 голосов
/ 23 июня 2011

Вопрос относительно шаблона устранения неоднозначности был дан здесь:

шаблон устранения неоднозначности

и в ответе мы можем прочитать:

ISO C ++03 14.2/4

Когда после имени появляется название специализации шаблона участника.или -> в выражении postfix или после спецификатора nested-name в квалифицированном идентификаторе, а выражение postfix или квалифицированный идентификатор явно зависит от параметра-шаблона (14.6.2), имя шаблона элемента должно бытьс префиксом шаблона ключевого слова.В противном случае предполагается, что имя не является шаблоном.

Теперь приведу мой конкретный пример, который я не совсем понимаю:

template <class T>
class Base {
  public:


  template <int v>
    static int baseGet() {return v;}

  class InnerA {
    public:

    template <int v>
      static int aget() {return v;}

  };

  class InnerB {
    public:
      typedef Base BaseType;
      typedef BaseType::InnerA OtherType;

      template <int v>
        static int baseGet() {return BaseType::baseGet<v>();} //(A)

      template <int v>
        static int aget() {return OtherType::aget<v>();} //(B)
  };
};

Очевидно, что он не компилируется.Вам нужно template в строке (B): OtherType::template aget<v>();.Однако и g ++ (4.4.3), и clang ++ (2.9) не жалуются на отсутствие template в строке (A).Зачем?BaseType зависит от типа T, не так ли?Это небольшое отклонение от стандарта этими компиляторами, или я что-то неправильно понимаю в стандарте?

Ответы [ 3 ]

8 голосов
/ 23 июня 2011

Они реализуют спецификацию C ++ 0x, где Base - это текущее значение .И C ++ 0x позволяет опустить ключевое слово template в таком случае.Так как BaseType является typedef для Base, когда вы говорите BaseType, это также указывает на текущую реализацию.

Чтобы процитировать спецификацию, поскольку вас, похоже, интересуют спецификации, ссылки

Имя является членом текущей реализации , если оно является [...]

  • Квалифицированный идентификатор, в котором спецификатор вложенного имени ссылается на текущий экземпляр , а при поиске ссылается как минимум на один член текущегоэкземпляр или независимый базовый класс.

и

Имя относится к текущему экземпляру , если оно [...]

  • в определении [...] вложенного класса шаблона класса, [...], имя введенного класса (раздел 9) классашаблон или вложенный класс

и (указанный вами измененный 14.2 / 4)

[...] или спецификатор вложенного имени вквалифицированный идентификатор относится к зависимому типу, но имя не является членом текущего экземпляра (14.6.2.1), имя шаблона элемента должно начинаться с префикса ключевого слова template.[...]


Примечание. В C ++ 03 ваш код некорректен, поскольку оба BaseType и OtherType являются зависимыми.Спецификация гласит:

Тип зависит, если он [...]

  • параметр шаблона
  • квалифицированный идентификатор с вложеннымспецификатор-имени, который содержит имя-класса, которое именует зависимый тип
  • идентификатор шаблона, в котором либо имя шаблона является параметром шаблона, либо любой из аргументов шаблона является зависимым типом

(обратите внимание, что Base эквивалентно Base<T>, который является основой, на которой Base и BaseType::InnerA являются зависимыми типами).

Обратите внимание, что выражение "явно зависит" в вашей цитате - это предстандартный термин, от которого довольно недавно избавились (полагаю, это было в декабре 1996 года).В основном это означало (в этом контексте) квалифицированный идентификатор, в котором спецификатор является зависимым, или доступ к члену класса (a->x / a.x), где a был зависимым.После того, как «явная зависимость» была удалена из черновика, в некоторых местах она все еще скрывалась, и даже в C ++ 0x все еще есть ссылки на «явную зависимость» в примечании в 14.6.2p2:

имя базового класса B<T>, имя типа T::A, имена B<T>::i и pb->j явно зависят от параметра-шаблона.

1 голос
/ 23 июня 2011

Поскольку OtherType является вложенным зависимым именем, а BaseType не является вложенным типом для начала.

Вам необходимо использовать template для вложенного зависимых типов.

Ключевые слова здесь:

  • Зависимый тип
  • Вложенный тип

Если тип - это то и другое, тогда вам нужно использовать шаблон .

  • OtherType - это как зависимый тип (зависит от T), так и вложенный тип
  • BaseType является только зависимым типом (зависит от T).Это не вложенный тип.
0 голосов
/ 23 июня 2011

BaseType зависит от типа T - но так же InnerB. Фактически, с точки зрения любого кода внутри BaseType<T>, он не зависит от T.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...