Я считаю, что Clang - единственный компилятор, который делает это правильно. Это не должно компилироваться. Пока аргумент fun
является набором перегрузки, который не содержит шаблонов функций, для каждого члена набора перегрузки будет предприниматься попытка выведения аргумента шаблона. Если вывод аргумента шаблона будет успешным для более чем одной из этих перегрузок, параметр функции станет неотчуждаемым контекстом [temp.deduct.call] /6.2.
В рассматриваемом примере аргументом fun
является набор перегрузки func
, который действительно не содержит шаблонов функций. Таким образом, для обоих перегрузок func
предпринимается попытка выведения аргумента для fun
, что успешно. В результате, параметр fun
становится не выводимым контекстом, что означает, что для Ret
не может быть выведен аргумент, и вызов завершается неудачно, так как нет кандидатов (именно на что жалуется clang).
Чтобы устранить неоднозначность этого вызова, просто явно укажите аргумент для первого параметра шаблона:
call<int>(mutableValue, func)