A lambda's return type can be deduced by the return value, so why can't a function's?

C++FunctionC++11LambdaAuto

C++ Problem Overview


#include <iostream>

int main(){
	
	auto lambda = [] {
		return 7;
	};
	
	std::cout << lambda() << '\n';

}

This program compiles and prints 7.
The return type of the lambda is deduced to the integer type based on the return value of 7.


Why isn't this possible with ordinary functions?

#include <iostream>

auto function(){
	return 42;
}

int main(){
	
	std::cout << function() << '\n';
}

error: ‘function’ function uses ‘auto’ type specifier without trailing return type

C++ Solutions


Solution 1 - C++

C++14 has this feature. You can test it with new versions of GCC or clang by setting the -std=c++1y flag.

Live example

In addition to that, in C++14 you can also use decltype(auto) (which mirrors decltype(auto) as that of variables) for your function to deduce its return value using decltype semantics.

An example would be that for forwarding functions, for which decltype(auto) is particularly useful:

template<typename function_type, typename... arg_types>
decltype(auto) do_nothing_but_forward(function_type func, arg_types&&... args) {
    return func(std::forward<arg_types>(args)...);
}

With the use of decltype(auto), you mimic the actual return type of func when called with the specified arguments. There's no more duplication of code in the trailing return type which is very frustrating and error-prone in C++11.

Solution 2 - C++

This is just a limitation of how the language was created and has evolved. In the upcoming C++14 standard the return type of a function can be deduced in some contexts, although not in all. There are complications when there are multiple return statements.

Additionally, deduced return types have other issues, for example, the return type of a template function cannot be used in a http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> context, as to be able to deduce the type, the compiler must instantiate the function template, which happens after substitution. The net result is that while the feature will be there in the near future, I would avoid it if you can provide the type yourself.

Solution 3 - C++

This is coming in c++14. See the following proposal.

Solution 4 - C++

Its not there still.. its gonna be in C++1y/C++14.. check out this link of feature

Solution 5 - C++

My guess is that it's probably because type-inferred lambdas can't be recursive.

Why does this matter? Because if a type-inferred lambda could be recursive (by "type-inferred" I mean where the variable's name is of type auto), then its return type could potentially depend on itself -- and while this is sometimes possible to solve, it much more difficult to implement than "simple" type inference. I'm not even sure if it's always solvable (is it decidable in the general case?). If functions supported type inference, though, this issue would have to be taken care of, so it's likely that they just excluded them for this reason.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTrevor HickeyView Question on Stackoverflow
Solution 1 - C++Mark GarciaView Answer on Stackoverflow
Solution 2 - C++David Rodríguez - dribeasView Answer on Stackoverflow
Solution 3 - C++user425495View Answer on Stackoverflow
Solution 4 - C++Hitesh VaghaniView Answer on Stackoverflow
Solution 5 - C++user541686View Answer on Stackoverflow