This uses trailing return type notation. This:
auto f() -> T { ... }
Is equivalent to this:
T f() { ... }
The advantage is that with a trailing return type notation you can express the type of a function based on expressions that involve the arguments, which is not possible with the classical notation. For instance, this would be illegal:
template <class T>
decltype(foo(t)) transparent_forwarder(T& t) {
// ^^^^^^^^^^^^^^^^
// Error! "t" is not in scope here...
return foo(t);
}
Concerning your edit:
Based on the above: What is wrong here?
template <typename T1, typename T2> auto sum(T1 v1, T2 v2) -> decltype(v1 + v2) { return v1 + v2; }
Nothing.
Concerning your second edit:
[...] It is using decltype without the need for -> in the function declaration. So Why do we need ->
In this case you don't need it. However, the notation that does use trailing return type is much clearer, so one may prefer it to make the code easier to understand.