Main Content

AUTOSAR C++14 Rule A7-1-5

The auto specifier shall not be used apart from following cases: (1) to declare that a variable has the same type as return type of a function call, (2) to declare that a variable has the same type as initializer of non-fundamental type, (3) to declare parameters of a generic lambda expression, (4) to declare a function template using trailing return type syntax

Since R2020b

Description

Rule Definition

The auto specifier shall not be used apart from following cases: (1) to declare that a variable has the same type as return type of a function call, (2) to declare that a variable has the same type as initializer of non-fundamental type, (3) to declare parameters of a generic lambda expression, (4) to declare a function template using trailing return type syntax.

Rationale

When you use the auto type specifier with a variable declaration, the type of the variable is deduced by the compiler. A developer reading the code might be confused if the type deduction is not what he or she would expect. The information needed to deduce the type might be in a separate part of the code.

This rule permits the use of the auto specifier in these cases:

  • You declare a variable that is initialized with a function call. This avoids a repetition of the type and ensures that there are no unexpected conversions if you change the return type of the function. For example, in this code snippet, variable var has the same type as the return type of myfunc():

    #include<cstdint>
    
    int32_t myfunc();
    
    int foo(){
      auto var=myfunc();
      return var;
    }

  • You declare a variable that you initialize with a non-fundamental type initializer. A type T is non-fundamental if std::is_fundatmental<T>::value is false. For a list of fundamental types, see Fundamental types. For example, the type of var in this code snippet is std::vector<int>::iterator.

    std::vector<int> v = { 1, 2, 3};
    auto var = v.begin();
    By using the auto keyword, you make the code more readable and avoid having to write a difficult to remember non-fundamental type.

    Note that a pointer is a non-fundamental type.

  • You declare the parameters of a generic lambda function. The function can then accept more than one kind of parameter types, similar to a function template. For instance, the custom implementation of std::sort in this code snippet can be used to sort vectors of ints, or floats, or other arithmetic types.

    //sort in ascending order
    std::sort(v.begin(), v.end(),
                  [](auto lhs, auto rhs){
                      return lhs < rhs});
    

  • You use a trailing return type syntax to declare a function template. In this case, there is no type deduction. The auto keyword is used as part of an alternative syntax for the declaration of function templates. This code snippet shows an example of trailing return type syntax.

    template<typename T, typename U>
    auto subtract(T lhs, U rhs) -> decltype(lhs - rhs);
    

Polyspace Implementation

  • Polyspace® flags the use of the auto specifier except when it is used in one of the cases listed in the previous section.

  • Polyspace flags the use auto to declare a variable that is initialized with a std::initializer_list of a fundamental type.

  • Polyspace does not flag the use of decltype(auto).

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include <string>
#include<vector>

auto func(int a)   // Non-compliant
{
    return a;
}

void func2()
{
    auto int_type = new int[5];           //  Non-compliant

    auto vector_type = std::vector<int> { 1, 2, 3 }; // Compliant

    const char* c = "hello";
    auto str2 =  std::string(c); // Compliant

    auto lambda = [](auto x, auto y) { // Compliant
        return x > y;
    };


}


In this example, the use of the auto specifier for the return type of func is non-compliant. The deduced return type of the function might not be obvious. Similarly, the use of auto in the declaration of int_type is non-compliant because the initializer of this variable is an array of type int, which is a fundamental type.

Other uses of auto in this example are compliant with the use cases specified by this rule:

  • The initializers of vector_type and str2 are non-fundamental types std::vector<int> and stdd::string respectively (use case (2)).

  • The initializer of variable lambda is a non-fundametal type lambda expression (use case (2))

  • Variables x and y are parameters of a lambda expression (use case (3)).

Check Information

Group: Declaration
Category: Required, Automated

Version History

Introduced in R2020b