Tag Archives: C++ auto

Auto keyword in C++

The keyword “auto” was first introduced in C++111 and was meant to provide an easier and cleaner way to write C++ code. But it has been a controversial feature since it came out because some believed that it’s making the C++ programming language into a dynamically typed language

Personally, I’d use auto as much as I can because it makes my code cleaner and also increases the readability (arguably).

The most common way to use keyword auto is using auto for variables. Of course, you will need a compiler that supports C++11 or higher. When using auto to declare variables, the compiler will do all the work to deduce its type, then codes will be changed/optimized during the compiling time. The following examples demonstrate how to declare variables with auto keyword:

auto x = 0;
auto y = Foo{};
auto z = std::mutex{};

The first line, without any following usage of the variable, will be deduced to type integer. The second line, however, utilizes the guaranteed copy elision1, introduced in C++17, which totally elided the usage of copy/move functions in this case, ensuring there is no temporary object created for moving or copying during the declaration process of object Foo. The same concept also applies to line 3, where I declared a non-movable and non-copyable object std::mutex and assigned it to variable z, well, the word “assign” isn’t quite accurate here because line 3 is basically the same as std::mutex z{};

As you can see, with auto keyword involved, primitive and object variable declaration can all look alike and distinguishable without confusion. while increasing the readability, performance is not at all affected by the existence of guaranteed copy elision.

The biggest advantage here is that you will never leave a variable uninitialized because the auto keyword requires the variable to be defined first.

You may wonder if auto is so convenient, can one use auto to replace template? No, there has not been a feature that allows the creation of a generic class purely using auto keyword, you might still want to stick with the template.

Using auto in functions

Auto keyword can also be used in function signatures. For example1,

class A {
    public:
        // A's constructor ...
        auto get() const -> const int& {
            return _f;
        }
    private:
        int _f;
};

In the above example, function get() returns a constant reference to the private variable _f. The trailing return type can be emitted by adding & after auto to indicate it’s returning a reference1:

class A {
    public:
        // A's constructor ...
        auto& get() const {
            return _f;
        }
    private:
        int _f;
};

To return the value and also keep the function’s constant constraint, simply change the trailing return type to int or remove it.

class A {
    public:
        // A's constructor ...
        auto get() const {
            return _f;
        }
    private:
        int _f;
};

One can argue that adding auto in function signatures makes them more confusing because one can’t easily tell the return type by looking at the function header, but I’d say it’s rarely the case. As long as the function name is descriptive and the return type is clear, this will increase the code readability.

Auto return type forwarding

When we try to forward the returned reference from a function to another function and return it, we do something like:

int& getAgain () { 
    return get();
}

Ok, let’s make this function “better” by involving auto keyword:

auto getAgain () {  // returns int instead of int& 
    return get();
}

Then we run into a problem. The function getAgain() does not actually return the reference, it deduces the forwarded variable from get() as int. To fix this, we will have to use decltype():

decltype(auto) getAgain () {  // returns int& 
    return get();
}

This way, we won’t have to explicitly declare the return type as auto& or auto.

References

  1. Andrist, Bjorn, and Viktor Sehr. C++ High Performance. 2nd ed., Birmingham, Packt, December 2020.