, если я положу static_assert(false)
в неиспользованный, компиляция не удастся.Означает ли это, что он создан?
Нет.Компилятор выполняет некоторые базовые проверки определения шаблона.Все в определении должно быть допустимым C ++, но некоторые вещи, которые зависят от параметра шаблона, не могут быть проверены до фактической реализации, когда известны аргументы шаблона.Так как static_assert(false);
не зависит от каких-либо параметров шаблона, он всегда вызывает ошибку, и компилятору разрешено замечать ошибку, даже если шаблон никогда не создается.
Если вы действительно хотите шаблон, который никогда не долженбыть созданным, обычный способ - использовать =delete
для шаблона функции или оставить шаблон класса неопределенным.
Но я не понимаю правил, чтобы знать, почему я не получаю foo<int*>(int**)
для первого.
В большинстве контекстов, которые называют специализацию шаблона функции, есть правило, что любой шаблон, который "более специализирован", чем все другие жизнеспособные перегрузки, является тем, который используется,Точное определение «более специализированного» является немного хитрым, но основная идея состоит в том, что если любой список аргументов, который может быть взят шаблоном функции «A», мог бы также быть взят шаблоном функции «B», но не наоборот,тогда «А» является более специализированным.В вашем примере
template <typename T> void foo(T*); // #1
template <typename T> void foo(T**); // #2
, если аргумент arg
имеет тип U**
для любого типа U
, так что вывод аргумента шаблона для шаблона # 2 для foo(arg)
может быть успешным с T=U
, мыможно увидеть, что вывод аргумента шаблона для шаблона # 1 для foo(arg)
также может быть успешным с T=U*
.С другой стороны, вполне возможно, что другой аргумент arg2
может означать, что аргумент шаблона для foo(arg2)
может быть успешным для шаблона # 1, но не для шаблона # 2, например, если arg2
имеет тип int*
.Таким образом, шаблон функции # 2 более специализирован, чем шаблон функции # 1.Это означает, что выражение типа foo(arg)
всякий раз, когда вычитание типа для обоих завершается успешно (и нет никаких других задействованных перегрузок), означает использование шаблона # 2.
То же самое "более специализированное" правило применяется в вашемявное создание
template void foo(int**);
Как и в случае выражения вызова функции, компилятор будет использовать дедукцию аргумента шаблона, чтобы увидеть, соответствует ли данное объявление каждому шаблону функции.В этом случае оба успешны, но поскольку шаблон №2 более специализирован, объявление интерпретируется как специализация №2, а не №1.
Все это заставляет меня понять, что я не совсем понимаючто происходит, когда компилятор видит вызов, который требует создания шаблона.Сканирует ли он шаблоны, пока не находит работающий, а затем останавливается?Или он создает все допустимые параметры (а затем что-то отбрасывает ненужные из объектного файла)?
Грубая последовательность для большинства случаев использования имени перегруженного шаблона функции:
Выполните поиск по имени, чтобы определить список шаблонов функций и функций, которые необходимо рассмотреть.
Для каждого шаблона функции в списке попытайтесь вывести аргумент шаблона.Если вывод аргумента шаблона завершается неудачей или если замена какого-либо аргумента шаблона в тип функции не удалась, игнорируйте этот шаблон с этого момента.В случае успеха это приводит к аргументу шаблона для каждого параметра шаблона и одному конкретному типу функции для специализации.
Разрешение перегрузки выполняется в основном так же, как и для шаблонов безнабор не шаблонных функций, изначально ищущих в сочетании с набором специализаций шаблонов функций, определенным выше.Но если две функции-кандидата нельзя упорядочить, чтобы сказать, что одна перегрузка лучше, чем другая, только на основе типов параметров и неявных преобразований, то функция без шаблона превосходит специализацию шаблона функции и специализацию из более специализированного шаблона функции.превосходит специализацию из менее специализированного шаблона функций.
Обратите внимание, что в ходе этого процесса создаются типы функций, но не определения специализаций шаблонов функций.