В соответствии со стандартом C ++ 17 [temp.deduct.call] / 3:
... Если P
является ссылочным типом, тип, на который ссылается P
используется для вывода типа....
Здесь P
равно T&
, поэтому компилятор удаляет ссылку и сравнивает T
с типом аргумента x+y
.Поэтому он выводит T
как int
.Затем на этапе разрешения перегрузки возникает ошибка, поскольку значение r * типа int
не может быть связано с параметром типа int&
.
Вывод аргумента шаблона должен происходить до разрешения перегрузки, поскольку в противном случае компиляторне будет знать, какие типы параметров использовать для разрешения перегрузки.