C++11 introduced the auto and Decltype keyword implementation of the type deduction, through these two keywords can not only convenient to obtain complex types, but also can simplify writing, improve coding efficiency.
The type deduction for auto and Decltype is done by the compiler at compile time, and auto is derived from the actual type by defining the value of the expression given when the auto variable is declared, and must be initialized immediately when declaring the auto variable Decltype the actual type by the value of the expression, but can only declare the variable without assigning a value.
Auto Type deduction
1. Auto derivation
Auto x = 5; deduced by the compiler as int type auto pi = new auto (1),//compiler deduced to int const auto* v = &x, u = 5;//v is const int*, U is const int
static Auto y = 0.1; Y is static const double auto S;//Error! Auto variable cannot only declare non-initialized
2. Auto Derivation rules
(1) When not declared as a pointer or reference, the derivation result of auto and the type of initialization expression after discarding the reference and CV-qualifier are the same; (CV-qualifier: const volatile qualifier)
(2) when declared as a pointer or reference, the derivation result of auto retains the CV-qualifier of the initialization expression.
int x = 0; Auto *a = &x; A for int* auto B = &x;//b for Int*,auto can automatically identify pointer type auto &c = x;//c to int& Const auto e = x;//e to const int Auto F = e;//f is int (not pointer or reference, CV qualifier is not preserved) const auto& g = x;//g is const int& auto& h = g;//h is Const int& (pointer or reference, retaining CV-qualifier) auto k = g;
3. Limitations of Auto
(1) Auto cannot be used for function parameters
(2) Auto cannot be used for non-static member variables
(3) Auto cannot define an array
(4) Auto cannot deduce the template parameters
void func (Auto a = 1) {}; Error. Auto cannot be used for function parameters
struct foo{
Auto var1 = 0; Error, auto cannot be used for amorphous member variables
static const Auto VAR2 = 0;
}
Template<typename t>
struct bar{};
int main () {
int arr[10] = {0};
Auto AA = arr; AA is deduced as int*
Auto rr[10] = arr; Error, auto cannot define array
Bar<int> Bar;
bar<auto> BB = bar; Error, auto cannot deduce template parameter
}
4. Auto's usage scenario
(1) Variable type name is relatively long and complex
such as STL container std::map< Double, double> result_map; std::map< double, double>::iterator it = Result_map.begin (); for (; it! = Result_map.end (); + + it) {}; The auto can be simplified to for (auto it = Result_map.begin (); It! = Result_map.end (); ++it); std::unordered_multimap< int, int> result_map; std::p air< std::unordered_multimap< int, int>::iterator, std::unordered_multimap< int, int>::iterator > Range = result_map.equal_range (key); Simplified to auto range = Result_map.equal_range (key) via auto;
(2) Unable to determine why the variable should define the type
Class Foo{public: static int get (void) { return 0; }}; Class Bar{public: static const char* get () { return "Hello World"; }}; Template<typename a>void func (void) { auto val = A::get (); cout << val << Endl;} int main () { func<foo> (); Func<bar> ();}
decltype Type derivation
1. Decltype Derivation
Decltype can deduce the type of an expression at compile-time, with the following syntax:
Decltype (exp). Decltype simply infers the type of the expression and does not evaluate the expression.
int x = 0; Decltype (x) y = 3; Y is deduced to be of type int decltype (x + y) z = 0;//z is deduced as int const int a = 1; Decltype (a) b = 2; The CV-qualifier const int& i = 9 is deduced as a const int, although not a pointer or reference; Decltype (i) h = x; Const int& decltype (z) * p = &x;//p for int*
Decltype the type obtained by the expression, you can retain the reference to the expression and the const qualifier. for a generic token expression, decltype precisely infers the type of the expression definition itself and does not discard the reference and CV qualifiers as Auto does .
2. Decltype Derivation rules
(1) Exp is an identifier, class access expression, Decltype (exp) and exp are of the same type
(2) Exp is a function call, Decltype (exp) and the type of return value are consistent
(3) Other cases, if exp is an lvalue, then Decltype (exp) is an lvalue reference of the exp type, otherwise the same as the exp type.
(1) Exp is an identifier, class access expression, Decltype (exp) and exp type consistent (2) exp is a function call, Decltype (exp) and the type of return value are consistent (3) other cases, if exp is an lvalue, then Decltype (exp) is an lvalue reference of the exp type, otherwise the same as the exp type. ' (1) identifier, class access expression, the type of Decltype (exp) and exp is the same as class foo{public:static const int number = 0; int x;}; int n = 0;volatile Const int& x = N;decltype (n) a = n; Intdecltype (x) b = n; Volatile const Int&decltype (foo::number) c = 0; const int (no static) Foo Foo;decltype (foo.x) d = 0; int type (2) function call, Decltype (f (XX)) and function return value type consistent const Foo F () {...} Decltype (f ()) C; Const FOO (3) parenthesized expression and addition operation expression struct foo{int x;}; const foo foo = foo ();d Ecltype (foo.x) a = 0; A is deduced as int, according to derivation rule 1decltype ((foo.x)) b = A; B is deduced as a const int&,//because an lvalue is a left value based on foo.x, the parenthesis expression is also an lvalue. Then according to derivation Rule 3, return the Lvalue reference, Foo is a const foo, then foo.x is a const int type lvalue, then Decltype's derivation is const int&int n = 1, m = 2;decltype (n + m) c = 0; C is deduced to be int, n + M is the right value, then derivation Rule 3, Decltype (n + = m) d = C; D is deduced as an int & n + = M is an lvalue, then derivation Rule 3, the reference for EXP//Note at this point that N is still 1, not 3, because Decltype just deducesThe type of exp, not the EXP value
3. Practical Application of Decltype
(1) Automatic derivation type in generic programming
decltype(ContainerT().begin()) it_; //获得某种类型容器的迭代器
(2) Extracting variable types through variable expressions
Vector<int> v; .... Decltype (v):: Value_type i = 0; If you know that V is a vector, but you do not know the data type, you can use Decltype (v):: Value_type
return type post syntax, auto and decltype used together
int& foo (int& i), float foo (float& f),///two functions with the same name, but with different return values and parameter types. If you want to use a template to implement the invocation of two functions with the same name. Template<typename T>decltype (foo (val)) func (t&val) { return val;} This compiles, however, because the return value of C + + is the predecessor syntax, the parameter variable does not exist when the return value is defined, so it is not possible to use the predecessor Decltype (foo (val)) "To Obtain Decltype (foo (val)), Val does not exist" But it can be done by automatic type deduction of auto and Decltype. Template<typename t>auto func (t& val), Decltype (foo (val))//return value type { return foo (val);}
C++11--auto,decltype type derivation