Another small but convenient extension to C++11 is the possibility of using the auto
specifier to tell the compiler to work out the return type of ordinary functions. For example, in the following code
auto f(int x)
{
return x * x;
}
the compiler will correctly infer the type returned by f()
as an int
. This is also possible for forward declarations, that is the following statement is perfectly valid
auto f(int x);
however, the function cannot be used until its body is defined. Return type deduction has also been extended for lambda expressions. In fact, one limitation of C++11’s lambdas was the fact that its return type (if none was specified) could only be deduced if the lambda’s body consisted of only a return statement, in which case the return type was inferred from the return expression, otherwise it was considered to be void
. The following code, for example, was ill-formed
int g(int x) { return x; }
auto f = [](int x)
{
auto y = g(x);
return y;
};
In order for it to work, a trailing-return-type had to be provided, as in the below code
auto f = [](int x) -> int
{
auto y = g(x);
return y;
};
With C++14 all lambda expressions have an auto
return type by default (if none is specified) that’s not limited to bodies with a single return
statement.
// implies -> auto
auto f = [](int x)
{
if (x > 0)
return true;
return false; // OK: consistent return types, deduced bool
};
If multiple return
statements exist they must all resolve to the same type, otherwise the program is ill-formed.
auto f = [](int x)
{
if (x > 0)
return true;
return 1.5; // ERROR: mismatching return types
};
Also, C++11 forbade the use of auto
in trailing-return-types, which meant that returning deduced reference types could not be possible. C++14 eliminated this restriction, so that we can now write
auto f = [](T& x) -> auto&
{
return x;
};
to specify that a lambda returns a deduced reference type. Return type deduction also works for templates, as shown in the following code
template <typename T>
auto& f(T& x)
{
return x;
}