auto
and
decltype(auto)
are
placeholder types that will be deduced later, based on the type of their (unambiguous) initializers.
In C++11, If you use
auto
as a leading return-type you must add a explicit trailing return-type specifier.
In C++11 and later, the arrow only must be used to allow return-type deduction based on names which aren't visible at the leading return type
. You need it to use the name
t
(declared in the parameter list!) in the specification of the explicit return type.
Since C++14, return-type deduction eliminates many of the cases where the arrow must be used. You can just usually write
auto
(or
decltype(auto)
) as the leading return type, and the placeholder type
auto
will be deduced based on the rules of template argument deduction. If that result type can't be deduced, you'll need to specify one explicitly.
But as you've seen, there is a subtle difference between the following two forms, which explicitly specifies the return type, and the latter two, which don't:
auto function(T& t) -> decltype(fc_overload(t)) { ... }
vs.
decltype(auto) function(T& t) { ... }
vs.
auto function(T& t) { ... }
.
The interesting difference is between the second two because you don't
really need the name
t
; the first form can be rewritten as
1 2
|
template <typename T>
decltype(fc_overload(std::declval<T>())) function(T& t) { ... }
|
. It's uglier, but equivalent.
See
https://isocpp.org/wiki/faq/cpp14-language#decltype-auto