Я задал этот вопрос авторам библиотеки в MS и получил чрезвычайно информативный ответ от Стефана Лававея, поэтому я полностью доверяю этой информации.
Произошла ошибка компиляции, которую вы получите в случае шаблонак тому факту, что вывод аргумента шаблона выполняется до разрешения перегрузки, а вывод аргумента шаблона требует точных совпадений для добавления чего-либо к набору перегрузки.
В деталях вычитание аргумента шаблона просматривает каждую пару типа параметра P и типа аргумента A и пытается найти замены шаблона, которые приведут к точному совпадению A P. После нахождения совпадений для каждогоВ качестве аргумента он проверяет согласованность (поэтому, если вы вызываете bar(foo<T>, foo<T>)
с T = int для первого параметра и T = double как вторым, это также дает сбой).Только после того, как в сигнатуре функции успешно подставлены согласованные совпадения, эта сигнатура добавляется в набор функций-кандидатов для разрешения перегрузки.
Только после того, как все обычные функции (найденные путем поиска по имени) и сигнатуры шаблонов соответствующих функций имеютв набор перегрузки был добавлен прогон разрешения перегрузки, после чего все эти сигнатуры функций оцениваются на «лучшее соответствие», в течение которого будут рассматриваться неявные преобразования.
Для случая operator+(foo<T>, foo<T>)
сfoo<int> + 5
, вычет аргумента шаблона не может найти подстановку для T, которая сделает выражение foo<T>
точно match int
, так что перегрузка operator + отбрасывается как кандидат, и неявное преобразование никогда не выполняетсядаже видно.
Мнение здесь, по-видимому, таково, что это, как правило, хорошая вещь, поскольку делает шаблоны намного более предсказуемыми, оставляя царство странного неявного поведения для разрешения перегрузки.
Стандартесть что сказать по этому поводу:
14.8.2.1 Вывод аргументов шаблона из вызова функции
"Вывод аргумента шаблона выполняется путем сравнения каждого типа параметра шаблона функции (назовите его P) с типом соответствующего аргумента вызова (назовите его A), как описано ниже....
... В общем, процесс дедукции пытается найти значения аргументов шаблона, которые сделают выведенный A идентичным A (после преобразования типа A, как описано выше) "
* 1031Далее следует перечислить несколько особых случаев, когда в этом правиле есть исключения, включающие cv-квалификаторы (поэтому T & будет совместим с const T &), и сопоставление производных классов (в некоторых случаях оно может соответствовать Derived & и Base &), но в основном точноесоответствие - это правило.