The compiler needs that information for checking, and the programmer, and the maintenance programmers who follow behind, need that information so they know how to call the thing. On the other hand, you can usually infer the result types of expressions by a simple forward process.
Possibly unpopular opinion: I am wary of relying on type inference for return types, other than for a function defined locally where you can easily see the implementation at the same time as the code calling it. Code like
auto x = calculate_some_complicated_thing()
...
do_something_with(x)
has a similar obscurity problem to code like
do_something_impressive(true, false, false, true)
in that to understand what the code is doing at this level, you have to read the interface documentation for the function you’re calling anyway, and then you’re hoping that you get everything in the right place because your tools might not be able to warn you if you don’t.
In practice, type inference for return types works fine for the work I do (iOS development). Initializers are blindingly obvious anyway, and other functions are often members of an object or a struct. There are barely any bare functions.
Possibly unpopular opinion: I am wary of relying on type inference for return types, other than for a function defined locally where you can easily see the implementation at the same time as the code calling it. Code like
has a similar obscurity problem to code like in that to understand what the code is doing at this level, you have to read the interface documentation for the function you’re calling anyway, and then you’re hoping that you get everything in the right place because your tools might not be able to warn you if you don’t.