Я думаю, что вы можете быть запутаны между rvalues и квалификатором const. function
возвращает неконстантное временное значение типа int, поэтому компилятор выводит T как int, как и должно быть. Как вы указали, вы можете привязать временное к const ref (c ++ 03 12.2 / 5), но компилятор не будет добавлять квалификаторы cv, чтобы сделать вызов функции правильно сформированным. Поскольку вы не можете управлять функцией шаблона, есть два пути решения этой проблемы (в дополнение к опубликованному вами решению).
(1) Явные параметры шаблона: function2<const int>(function())
(2) квалификационный возврат: const int function();
Оба эти решения хорошо сформированы. (1) кажется лучшим решением, ИМХО, поскольку (2) нетрадиционно и глупо.
Редактировать: На самом деле, выводимый тип может быть более квалифицированным по cv, чем аргумент для аргумента шаблона ref, но только в том случае, если в противном случае вывод типа завершится неудачей (c ++ 03 14.8.2.1/3). В этом случае дедукция типа не дает сбоя, но приводит к неправильному вызову функции (SFINAE не применяется, поскольку специализация шаблонной функции сама по себе не деформирована).
Если цель автора шаблона заключалась в том, чтобы не изменять аргумент, он должен быть объявлен как ссылочный аргумент const, так что это может быть ошибкой в библиотеке шаблонов, или это может изменить аргумент, и в этом случае вы выполнение не удастся, когда функция попытается изменить аргумент.
Редактировать: Как указывает FredOverflow, не-классные значения всегда cv безоговорочно соответствуют стандарту 3.10 / 9. Итак, (2), который работает в gcc 4.3, на самом деле является ошибкой компилятора (gcc <4.5, согласно FredOverflow). </p>