Previously I discusses suffix return types, and I provided an example of how it could simplify notation. This:
Icanos::System::String Icanos::System::FormattedLog::ApplyIndent(const String&);
became this, which I’m sure you’ll agree is tidier:
auto Icanos::System::FormattedLog::ApplyIndent(const String&) -> String;
However, there is another application which is perhaps more relevant. The above example is a matter of scope: String is not in scope before the function’s name, but it is after, so we don’t have to qualify it fully. But the following is also to do with scope.
Consider a C++ template function to find the quotient of two values (yes, I know it’s contrived…). It’s return type depends on the template types passed to it. Indeed, it’s return type is decltype(s / t) where s and t are the values to be divided. But we can’t put this as s and t aren’t in scope before the parameter list. They are, however, in scope after it.
template <class S, class T>
auto quotient(S s, T t) -> decltype(s / t)
{
return s/t;
}
And there we are. It works beautifully! Just as a contrast, here is how Dr. Stroustrup says you would have to do it with C++03/98 syntax. As he points out, it is much more messy.
template <class S, class T>
declytype(*(S*)(0) / *(T*)(0)) quotient(S s, T t)
{
return s/t;
}
While s and t aren’t in scope before the parameter list, S and T (the types themselves) are in scope. Thus we can cast 0 to a null pointer to S and a null pointer to T, and then dereference it. This wouldn’t be acceptable at runtime, but it works as decltype is evaluated at compile time. Though it works, the former solution is clearly nicer.
Read more about it on his FAQ.