Определены ли определяемые пользователем руководства по дедукции, включающие шаблонный шаблонный шаблон, в качестве шаблона для стандартного руководства

Фон

Вчера я задал вопрос о гарантиях использования руководств для вычетов в случае шаблонных параметров шаблона. Я был очень удивлен, когда Барри изменил свой ответ на подтверждение стандартной совместимости кода. Мое удивление на самом деле не объясняется тем фактом, что гистограммы дедукции могут применяться для параметров шаблона шаблона, но больше от стандартной части, которая соответствует этому соответствию, а именно [temp.param]/3:

Параметр типа, идентификатор которого не следует за многоточием, определяет его идентификатор как typedef-name (если объявлено без template) или имя шаблона (если объявлено с помощью template) в области действия объявления шаблона.

Этот плюс [temp.deduct.guide]/1 и правило для simple-template-id позволит создать общий гид вычитания, принимающий любой шаблон.

Пример

#include <string>

template <class T>
struct Foo {
   Foo(T) { }
};

template <template <class> class TT>
TT(const char *) -> TT<std::string>;

int main() {
    Foo foo("abc");
}

Вопрос

Код вызывает gcc для сбоя с внутренней ошибкой и приводит к ошибке компиляции в clang. Чтобы быть прямым, я не, говоря, что код должен быть фактически разрешен на С++, но думаю, что текущая формулировка делает его совместимым. Я пропустил какое-то важное правило, которое запрещает код?

Ответ 1

Ваш пример

Если вы ошибаетесь, я бы назвал теперь удаленный ответ

Если я не ошибаюсь, это противоречит [temp.deduct.guide] p3:

Идентификатор простого шаблона должен указывать специализацию шаблона класса.

TT<std::string> не указывает специализацию шаблона класса, а ваш код плохо сформирован.

Существует также это в [temp.spec] p4:

Специализация - это класс, функция или член класса, который либо создан, либо явно специализирован.

TT является технически параметром типа шаблона. Конструкция TT<std::string> является зависимым от типа именем типа. Если руководство по удержанию будет фактическим шаблоном функции, и мы его создадим, TT<std::string> может быть создан как имя класса, относящееся к специализации шаблона класса. Он также может ссылаться на int, если TT создается для ссылки на подходящий шаблон-псевдоним. Но как есть, в объявлении-указателе дедукции он еще не назвал специализацию шаблона класса.

В [temp.res] p8.5.5 существует правило:

В противном случае для шаблона, для которого может быть создана действительная специализация, не выдаётся никакой диагностики.

Итак, может ли вообще быть специализация гида-гида? Я утверждаю, что нет. Прежде всего, это не "шаблонный объект" (c.f. [temp] p8), который может быть создан. То, что специализируется в выводе аргумента шаблона шаблона, представляет собой набор шаблонов, которые формируются на основе руководств по вычитанию, но не самими направляющими. См. [Over.match.class.deduct] p1.4

[...] Для каждого гида-указателя создается шаблон функции или функции со следующими свойствами [:]: [...]

Это те шаблоны функций, которые дополнительно специализируются в процессе перегрузки. Вывод руководства сам по себе никогда не специализируется, поэтому мы можем создать диагностическое сообщение о нарушении правила, согласно которому простой шаблон-идентификатор в руководстве по вычитанию не называет специализацию шаблона класса.

Именование по шаблону псевдонима (пример Ричарда)

Ричард дал другой пример

template<typename T> class X { T t; };
template<typename T> using Y = X<T*>;
template<typename T> Y(T) -> Y<T>;

В этом случае это сложнее, и я думаю, что это может быть разрешено формулировкой, так как Y<T> на самом деле является специализацией шаблона класса. Теперь вы можете спорить о том, на самом деле ли он называет специализацию или просто обозначает ее, после применения правил перезаписи. Тот факт, что он может допускать аргументы, кажется достаточным, чтобы гарантировать отчет о дефектах, IMO.