Начиная с C ++ 17, вам не нужно ключевое слово template
между ::
и именем специализации шаблона элемента в определенных контекстах, которые могут именовать только тип, включая спецификатор имени-типа синтаксис, который используется в шаблоне псевдонима LocalChecker
. Таким образом, clang и MSV C неверно отклоняют эту строку без template
и, возможно, еще не реализовали это изменение.
C ++ 14 [temp.names] / 4:
Когда имя специализации шаблона элемента появляется после .
или ->
в постфиксном-выражении или после вложенного-спецификатора-имени в квалифицированный-идентификатор , а объектное выражение постфиксное-выражение зависит от типа или спецификатор вложенного-имени в квалифицированный-идентификатор относится к зависимому типу, но имя не является членом текущего экземпляра (14.6.2.1), имя шаблона элемента должно начинаться с ключевого слова template
. В противном случае предполагается, что имя не является шаблоном.
было заменено на C ++ 17 [temp.names] / 4 :
Ключевое слово template
, как говорят, появляется на верхнем уровне в квалифицированный-идентификатор , если оно появляется за пределами списка-аргументов-шаблона или спецификатора-объявления . В квалифицированный-идентификатор из идентификатор-декларатора или в квалифицированный-идентификатор , сформированный имя-заголовка класса или enum-head-name , ключевое слово template
не должно появляться на верхнем уровне. В квалифицированный-идентификатор , используемый в качестве имени в спецификатор-типа , спецификатор-разработанного-типа , объявление-использования , или class-or-decltype , необязательное ключевое слово template
, появляющееся на верхнем уровне, игнорируется. В этих контекстах всегда предполагается, что токен <
представляет список аргументов-шаблонов . Во всех других контекстах, при именовании специализации шаблона элемента неизвестной специализации ([temp.dep.type]), имя шаблона элемента должно начинаться с префикса ключевого слова template
.
Поскольку приведенные выше правила требуют только ключевое слово template
при названии специализации шаблона элемента, а не только сам шаблон элемента, может показаться, что простой T::Checker
в дополнение к T::template Checker
должен работать в части примера. используя is_detected
. (Нам не нужно typename
, поскольку мы называем шаблон псевдонима, а не тип, который является специализацией этого шаблона.) Но не ясно, почему добавление шаблона должно иметь значение, когда компилятор делает или не делает Мне не нужна помощь в определении смысла. Открытая проблема CWG 1478 связана.
В любом случае компиляторам, похоже, больше нравится подсказка template
: ваша программа с is_detected<T::template Checker,
... компилируется успешно на clang ++, g ++ и msv c: см. на godbolt .