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

Фон

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

параметр-тип, идентификатор которого не следует за многоточием, определяет его идентификатор как typedef-name (если объявлен без template) или template-name (если объявлено с 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. Честно говоря, я не говорю, что код действительно должен быть разрешен в C ++, но думаю, что текущая формулировка действительно делает его совместимым. Я упустил какое-то важное правило, запрещающее код?


person W.F.    schedule 07.10.2017    source источник
comment
О чувак. Надеюсь, это запрещено :)   -  person Barry    schedule 07.10.2017
comment
@Barry yep, это было бы очень неприятно :) Это может быть явно запрещено, чтобы минимизировать влияние на другие части стандарта ...   -  person W.F.    schedule 07.10.2017
comment
От Ричарда Смита, смеется: Ха, мы никогда не предполагали, что это будет действительным, но я не вижу в нынешней формулировке правила, запрещающего это. В конечном итоге это станет дефектом основного языка.   -  person Barry    schedule 08.10.2017
comment
@Barry см. Мой ответ ниже   -  person Johannes Schaub - litb    schedule 12.11.2017


Ответы (1)


Ваш пример

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

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

Простой-template-id должен называть специализацию шаблона класса.

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

Это также есть в [temp.spec] p4:

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

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

В [temp.res] p8.5.5 есть правило, которое гласит

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

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

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

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

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

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

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

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

person Johannes Schaub - litb    schedule 12.11.2017
comment
Я не знаю, как вы это делаете, но вы всегда меня поражаете;) Позвольте мне проанализировать ваш ответ еще немного, чтобы убедиться, действительно ли я его понимаю :) - person W.F.; 12.11.2017
comment
@ W.F. мой аргумент в том, что он не называет специализацию шаблона класса. Примечательно, что это зависит. Но причина не в этом. В Foo<T> имя Foo<T> обозначает (неизвестную) специализацию шаблона класса Foo, поэтому оно обозначает специализацию шаблона класса. Но в TT<std::string> он называет еще неизвестный тип (отсюда и мое замечание, что это зависимый тип). Поэтому во время определения руководства по выводам имя не указывает на специализацию шаблона класса. - person Johannes Schaub - litb; 12.11.2017
comment
да - извините, я снова перечитал ваш (как я уже сказал, умопомрачительный) ответ, и я думаю, что понимаю вашу точку зрения о зависимом type-name ... Я не видел его раньше как TT (AFAIK) на самом деле невозможно вывести, если это псевдоним ... Я думаю, что это может быть ответ, и, возможно, здесь все-таки нет языкового дефекта ... - person W.F.; 12.11.2017