Рассмотрим следующий код:
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>)>); ^
Хотя я понимаю, что, как правило, тип параметра std::function
не может быть выведен, поскольку это не выводимый контекст
В этом случае T
может быть сначала выведен с помощью переданного аргумента 0
, а затем подставлен в std::function<void(S<T>)>
, чтобы получить std::function<void(S<int>)>
.
Я ожидаю, что после вывода T=int
, компилятор заменит T
везде в сигнатуре, а затем попытается создать параметр std::function
с аргументом g
.
Почему это не так? Я предполагаю, что порядок, в котором происходит замещение/вычет, как-то связан с этим, но я хотел бы увидеть соответствующую стандартную формулировку.
Дополнительный вопрос: может ли это быть чем-то потенциально изменено в будущем стандарте при сохранении обратной совместимости, или есть фундаментальная причина, по которой этот вид замены не работает?