C++: “auto” return type deduction

Before C++14, when implementing a function template, programmers did not know the return type of their functions and had to do something like this:

template <typename A, typename B>
auto do_something(const A& a, const B& b) -> decltype(a.do_something(b))
{
  return a.do_something(b);
}

Programmers had to use decltype to tell the compiler: “The return type of this method is the return type of the do_something method of object a.” The auto keyword was used to inform the compiler: “The return type of this function is declared at the end.”

Since C++14, coders can do something much simpler:

template <typename A, typename B>
auto do_something(const A& a, const B& b)
{
  return a.do_something(b);
}

Starting with C++14, the compiler deduces the return type of functions that use auto as the return type.

Restrictions:

All returned values must be of the same type. The example below will not even compile because it can return either an int or a double:

auto f(int n)
{
	if (n == 1)
    {
		return 1;
    }

	return 2.0;
}

For recursive functions, the first return value must allow the compiler to deduce the return type of the function, as in this example:

auto accumulator(int n)
{
	if (n == 0)
    {
		return 0;
    }

	return n + accumulator(n - 1);
}

Starting with C++20, a function can be declared like this and it will work properly:

auto do_something(const auto& a, const auto& b)
{
    return a.do_something(b);
}

When programmers define functions this way, if one or more function parameters are declared as auto, the entire function is treated as a template. So, while this new construction might seem to add more “functionality” to the auto keyword, it is really just a more convenient way of declaring function templates.

More posts about auto:

C++: “auto” on anonymous functions

C++14 introduced an improvement to the way programmers can declare anonymous functions (a.k.a. lambda expressions).

For example, before C++14, if programmers wanted to pass an anonymous function to the sorting algorithm, they had to do something like this:

Continue reading “C++: “auto” on anonymous functions”

C++: ‘auto’

Starting C++11, C++ contains a lot of improvements to the core language as well as a lot of additions to the standard library.

The aims for this new version, according to Bjarne Stroustrup were making C++ a better language for systems programming and library building, and making it easier to learn and teach.

auto is an already existing keyword inherited from C that was used to mark a variable as automatic (a variable that is automatically allocated and deallocated when it runs out of scope). All variables in C and C++ were auto by default, so this keyword was rarely used explicitly. The decision of recycling it and change its semantics in C++ was a very pragmatic decision to avoid incorporating (and thus, breaking old code) new keywords.

Since C++11, auto is used to infer the type of the variable that is being declared and initialized. For example:

int a = 8;
double pi = 3.141592654;
float x = 2.14f;

in C++11 and later, the code above can be declared in this way:

auto a = 8;
auto pi = 3.141592654;
auto x = 2.14f;

In the last example, the compiler will infer that a is an integer, pi is a double and x is a float.

Someone could say: “come on, I do not see any advantage on this because it is clearly obvious that ‘x‘ is a float and it is easy to me infer the type instead of letting the compiler to do that”, and yes, though the user will always be able to infer the type, doing it is not always as evident or easy as thought. For example, if someone wants to iterate in a std::vector in a template function, int the code below:

template <typename T>
void show(const vector<T>& vec)
{
    for (auto i = vec.begin(); i != vec.end(); ++i) // notice the 'auto' here
        std::cout << *i << std::endl;
}

the following declaration:

auto i = vec.begin();

in ‘old’ C++ would have to be written as:

typename vector::const_iterator i = vec.begin();

So, in this case, the auto keyword is very useful and makes the code even easier to read and more intuitive.

Anyway, there are restrictions on its usage:

  • Before C++20, it is not possible to use auto as a type of an argument of a function or method.
auto x = 2, b = true, c = "hello"; // invalid auto usage

Starting with C++14, the return type of functions can be deduced automatically (you can read more about that here). It can also be used in lambda expressions (more info here); . Starting with C++20, the arguments of a function can also be auto.

To read about auto see these links: