Reputation: 13424
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?
Upvotes: 4
Views: 510
Reputation: 217145
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.
Upvotes: 5
Reputation: 37513
The trivial example would be a situation when you want to invoke function before it is defined and returned type is deduced:
decltype(auto) bar(); // doesn't help
decltype(auto) foo() { bar(); } // error: returned type of `bar` is unknown
decltype(auto) bar() { foo(); }
Upvotes: 6