Я предполагаю, что путаница здесь связана с ролью аргументов шаблона по умолчанию.
Правило не так: попробуйте вывести параметр. Если вычет не удался, используйте значение по умолчанию (если оно предусмотрено).
Скорее, правило таково: если параметр находится в выведенном контексте, выведите его. Если вычет не удается, прервать. Если это не в выведенном контексте, и это не предоставлено явно, используйте аргумент по умолчанию. Другими словами, аргумент по умолчанию используется, только если параметр не находится ни в выведенном контексте, ни в явном виде.
В обоих ваших примерах ItrT
находится в выведенном контексте, поэтому аргумент шаблона по умолчанию вообще не рассматривается. Разница между ними заключается в том, что вы можете выводить T
из лямбды (вы просто соответствуете ее типу), но вы не можете выводить function<void(T)
из лямбды - лямбда может быть преобразовал в соответствующий function
, но лямбда не a function
. Шаблон вычета не делает преобразования. Вычисление шаблона просто соответствует шаблонам.