C++ auto type derivation

reference

http://c.biancheng.net/view/6984.html

Syntax and rules of auto type derivation

In previous versions of C + +, the auto keyword was used to indicate the storage type of variables, which is opposite to the static keyword. Auto means that variables are stored automatically, which is also the default rule of the compiler, so it is the same whether to write or not. Generally, we don't write either, which makes the existence of auto keyword very weak.

C++11 gives the auto keyword a new meaning and uses it for automatic type derivation. In other words, after using the auto keyword, the compiler will automatically deduce the type of variable during compilation, so we don't need to manually specify the data type of variable.

The basic usage syntax of auto keyword is as follows:

auto name = value;

Name is the name of the variable and value is the initial value of the variable.

Simple example of auto type derivation:

auto n = 10;
auto f = 12.8;
auto p = &n;
auto url = "http://c.biancheng.net/cplus/";

Let's explain:
In line 1, 10 is an integer, which is of type int by default, so it is deduced that the type of variable n is int.
In line 2, 12.8 is a decimal, and the default is double, so the type of derived variable f is double.
In line 3, the result of & n is a pointer of type int *, so it is deduced that the type of variable p is int *.
In line 4, the string surrounded by double quotation marks "" is const char * type, so the derived variable url type is const char *, that is, a constant pointer.

We can also define multiple variables consecutively:

int n = 20;
auto *p = &n, m = 99;

Let's first look at the first subexpression. The type of & n is int *, and the compiler will deduce that auto is int according to auto *p. The latter m variable is naturally of type int, so it is also correct to assign 99 to it.

Here we should note that there can be no ambiguity in the derivation. In this example, the compiler has deduced that auto is of type int according to the first sub expression, so the following m can only be of type int. if m=12.5 is wrong, because 12.5 is of type double, which conflicts with int.

Another noteworthy point is that variables derived using auto type must be initialized immediately, which is easy to understand, because auto is only a "placeholder" in C++11, not a real type declaration like int.

Advanced usage of auto

int  x = 0;
auto *p1 = &x;   //p1 is int *, auto is derived as int
auto  p2 = &x;   //p2 is int *, auto is derived as int*
auto &r1  = x;   //r1 is int &, auto is derived as int
auto r2 = r1;    //r1 is int &, R2 is int, auto derives int, & discarded

Let's explain:
In the second line of code, p1 is of type int *, that is, auto * is of type int, so auto is deduced to be of type int.
In the third line of code, auto is derived as int type, which has been demonstrated in the previous example.
In line 4, r1 is of type int & and auto is derived as of type int.
The code in line 5 needs to be emphasized. r1 was originally an int type, but auto was derived as an int type, which indicates that when the expression on the right of = is a reference type, auto will discard the reference and directly derive its original type.

Next, let's look at the combination of auto and const:

int  x = 0;
const  auto n = x;  //n is const int and auto is derived as int
auto f = n;      //f is const int, auto is deduced as int (const attribute is discarded)
const auto &r1 = x;  //r1 is const int & type, and auto is deduced as int
auto &r2 = r1;  //r1 is const int & type, and auto is deduced as const int type

Let's explain:
In line 2, n is const int and auto is derived as int.
In the third line of code, n is const int type, but auto is deduced as int type, which means that when the expression on the right of = has const attribute, auto will not use const attribute, but directly deduce non const type.
In the fourth line of code, auto is derived as int type, which is easy to understand and will not be repeated.
In line 5, r1 is const int & type, and auto is also derived as const int type, which means that when const is combined with reference, the derivation of auto will retain the const type of the expression.

Finally, let's briefly summarize the usage of the combination of auto and const:
When the type is not a reference, the const attribute of the expression will not be retained in the derivation result of auto;
When the type is reference, the const attribute of the expression will be retained in the derivation result of auto.

Limitations of auto

1. Variables must be initialized when using auto.
2. auto cannot be used in arguments to functions.
3. auto cannot act on non static member variables of a class (that is, member variables without static keyword modification).
4. The auto keyword cannot define an array.

char url[] = "http://c.biancheng.net/";
auto  str[] = url;  //arr is an array, so auto cannot be used

5. auto cannot act on template parameters.

template <typename T>
class A{
    //TODO:
};
int  main(){
    A<int> C1;
    A<auto> C2 = C1;  //error
    return 0;
}

Application of auto

Define iterators using auto

A typical application scenario of auto is the iterator used to define stl.

When using stl container, we need to use iterators to traverse the elements in the container; Iterators of different containers have different types, which must be specified when defining iterators. The types of iterators are sometimes complex and cumbersome to write. Please see the following example:

#include <vector>
using namespace std;
int main(){
    vector< vector<int> > v;
    vector< vector<int> >::iterator i = v.begin();
    return 0;
}

It can be seen that when defining iterator i, the type writing is lengthy and error prone. However, with auto type derivation, we don't have to do this. Just write an auto.

Modify the above code to make it more concise:

#include <vector>
using namespace std;
int main(){
    vector< vector<int> > v;
    auto i = v.begin();  //Use auto instead of a specific type
    return 0;
}

auto can deduce the type of variable i according to the type of expression v.begin() (the return value type of begin() function).

auto for generic programming

Another application of auto is when we don't know what type variables are or don't want to specify specific types, such as in generic programming. Let's move on to an example:

#include <iostream>
using namespace std;
class A{
public:
    static int get(void){
        return 100;
    }
};
class B{
public:
    static const char* get(void){
        return "http://c.biancheng.net/cplus/";
    }
};
template <typename T>
void func(void){
    auto val = T::get();
    cout << val << endl;
}
int main(void){
    func<A>();
    func<B>();
    return 0;
}

Operation results:

100
http://c.biancheng.net/cplus/

The template function func() in this example will call the static function get() of all classes and handle its return value uniformly, but the return value types of get() are different and cannot be converted automatically. This requirement is very troublesome to implement in the previous C + + version. It is necessary to add an additional template parameter and assign a value to the template parameter manually during the call to indicate the type of variable val.

However, with auto type automatic derivation, the compiler will deduce the type of val variable according to the return value of get(), so there is no need to add a template parameter.

The following code demonstrates a solution without using auto:

#include <iostream>
using namespace std;
class A{
public:
    static int get(void){
        return 100;
    }
};
class B{
public:
    static const char* get(void){
        return "http://c.biancheng.net/cplus/";
    }
};
template <typename T1, typename T2>  //An additional template parameter T2 is added
void func(void){
    T2 val = T1::get();
    cout << val << endl;
}
int main(void){
    //Assign values to template parameters manually when calling
    func<A, int>();
    func<B, const char*>();
    return 0;
}

Keywords: C++ Back-end

Added by TheBeginner on Sun, 27 Feb 2022 02:35:08 +0200