There have been many, many, many questions and answers regarding the trailing return type, auto
return type deduction and the very useful decltype(auto)
. But I failed to find an answer to whether the trailing return type is needed at all since we have decltype(auto)
. Are there cases that the trailing return type solves, where decltype(auto)
either cannot be used or doesn't work (gives unexpected / incorrect results) and the trailing return type was needed in the first place?
decltype(auto)
(and more generally deduced return type) and trailing return type are orthogonal features.
You can have:
decltype(auto) f() {}
auto f() -> decltype(auto) {}
trailing return type is fine especially to have access to context we don't have before the function name
as for template:
template <typename T>
auto f(T x) -> decltype(bar(x));
versus
template <typename T>
decltype(bar(std::declval<T&>())) f(T x);
or for dependent name in class:
auto C::begin() -> iterator;
versus
C::iterator C::begin();
The only place where it is required is for lambda (if you have/want to specify return type explicitly):
[]() -> some_type {/*...*/}
[]() -> auto {/*...*/}
(which is equivalent to []() {/*...*/}
)[]() -> decltype(auto) {/*...*/}
Case when we have to defining return type of lambda is when it should return reference type.
Done with decltype(auto)
and auto
.
decltype(auto)
and auto
deduction type differs, mostly as T&&
and T
.
Deduced return type requires definition of the body.
They also doesn't allow SFINAE, as there are no substitution.