Рассмотрим следующий код:
template <typename>
struct S { };
void g(S<int> t);
template <typename T>
void f(T, std::function<void(S<T>)>);
При попытке вызвать
f(0, g);
я получаю следующую ошибку:
error: no matching function for call to 'f'
f(0, g);
^
note: candidate template ignored: could not match
'function<void (S<type-parameter-0-0>)>'
against 'void (*)(S<int>)'
void f(T, std::function<void(S<T>)>);
^
живой пример на godbolt.org
Хотя я понимаю, что обычно тип параметра std::function
не может быть выведен, поскольку онне выводимый контекст
В этом случае T
может быть сначала выведен с помощью переданного аргумента 0
, а затем подставлен в std::function<void(S<T>)>
для получения std::function<void(S<int>)>
.
Я ожидаю, что после вывода T=int
компилятор заменит T
везде в сигнатуре, а затем попытается создать параметр std::function
с аргументом g
.
Почему это не так? Я предполагаю, что порядок, в котором происходит замещение / вычет, как-то связан с этим, но я хотел бы увидеть соответствующую Стандартную формулировку.
Бонусный вопрос: это то, что потенциально может быть изменено в будущем стандарте при сохранении обратной совместимости, или есть фундаментальная причина, по которой этот вид замены не работает?