Вопрос 1
Хотя может быть относительно легко изменить правила в ваших тривиальных случаях, обычно это не так.
Рассмотрим такой случай:
template <A, B, C> A f(B b, C c) { ... } // #1
int f(int a, int b) { ... } // #2
int f(int a, double b) { ... } // #3
И такой вызов:
double x = f(1, 2.0); // Call #1 or #3?
Таким образом, не всегда тривиально изменять правила и гарантировать, что существующий код продолжает работать. Такие изменения могут легко привести к двусмысленностям, вызову тихого изменения функции ...
Стандарт обычно избегают изменения языка таким образом, чтобы могли произойти неожиданные тихие изменения (или сделать законным код становится неоднозначным) .
Однако было бы неплохо, если бы существовал способ указать, что мы хотим вычитать возвращаемый тип в определенных c случаях. С помощью контекстного ключевого слова можно определить правила обработки таких случаев, как приведенный выше. Например, может возникнуть конфликт, если при использовании вывода типа возвращаемого значения предпочтительна перегрузка, которая отличается от перегрузки без вывода типа возвращаемого значения.
Вопрос 2
Нет, обычно не следует указывать тип, если он не нужен.
Альтернативы
Хотя решение для возврата объекта класса с операторами преобразования может работать, в некоторых случаях для них самым простым решением было бы изменить возвращаемое значение для выходного параметра.
template <class T> void zero(T &t) { t = 0; } // set_zero would be more readable
int x;
zero(x);
Я бы не считал это решение подходящим для этого случая, поскольку следующее намного яснее:
auto x = zero<int>();
На практике, учитывая, что значение по умолчанию равно нулю для числовых типов и для большинства других типов, тогда не может быть инициализировано целым числом или оно может не дать желаемого результата, было бы лучше просто написать:
int x = {};
или
int x {};