|
| 1 | +<!-- .slide: data-background="#111111" --> |
| 2 | +# Automatic type deduction |
| 3 | + |
| 4 | +___ |
| 5 | + |
| 6 | +## `auto` keyword |
| 7 | + |
| 8 | +```cpp |
| 9 | +auto a; // error: declaration of ‘auto a’ has no initializer |
| 10 | +auto i = 42; // i is int |
| 11 | +auto u = 42u; // u is unsigned |
| 12 | +auto d = 42.0; // d is double |
| 13 | +auto f = 42.0f; // f is float |
| 14 | + |
| 15 | +double f(); |
| 16 | +auto r1 = f(); // r1 is double |
| 17 | + |
| 18 | +std::set<std::string> collection; |
| 19 | +auto it = collection.begin(); // it is std::set<std::string>::iterator |
| 20 | +``` |
| 21 | + |
| 22 | +**Rationale**: Not important (but strongly defined) types, less typing, less refactoring. |
| 23 | +<!-- .element: class="fragment fade-in" --> |
| 24 | + |
| 25 | +* <!-- .element: class="fragment fade-in" --> A compiler can automatically deduce the type of variable during initialization |
| 26 | +* <!-- .element: class="fragment fade-in" --> Deduction is made from a literal, other variable or a function return type |
| 27 | +* <!-- .element: class="fragment fade-in" --> The same rules as for templates deduction are applied |
| 28 | + |
| 29 | +___ |
| 30 | + |
| 31 | +## Variable modifiers |
| 32 | + |
| 33 | +```cpp |
| 34 | +int func() { return 10; } |
| 35 | + |
| 36 | +int main() { |
| 37 | + const auto& v1 = func(); // v1 is const int& |
| 38 | + const auto v2 = func(); // v2 is const int |
| 39 | + // auto& v3 = func(); // error: cannot bind non-const lvalue reference |
| 40 | + // of type ‘int&’ to an rvalue of type ‘int’ |
| 41 | + auto v4 = func(); // v4 is int |
| 42 | + return 0; |
| 43 | +} |
| 44 | +``` |
| 45 | + |
| 46 | +___ |
| 47 | +<!-- .slide: style="font-size: 0.9em" --> |
| 48 | + |
| 49 | +### Deduction rules for references |
| 50 | + |
| 51 | +```cpp |
| 52 | +const vector<int> values; |
| 53 | +auto v1 = values; // v1 : vector<int> |
| 54 | +auto& v2 = values; // v2 : const vector<int>& |
| 55 | + |
| 56 | +volatile long clock = 0L; |
| 57 | +auto c1 = clock; // c1 : long |
| 58 | +auto& c2 = clock; // c2 : volatile long& |
| 59 | + |
| 60 | +Gadget items[10]; |
| 61 | +auto g1 = items; // g1 : Gadget* |
| 62 | +auto& g2 = items; // g2 : Gadget(&)[10] - a reference to |
| 63 | + // the 10-elementh array of Gadgets |
| 64 | + |
| 65 | +int func(double) { return 10; } |
| 66 | +auto f1 = func; // f1 : int (*)(double) |
| 67 | +auto& f2 = func ; // f2: int (&)(double) |
| 68 | +``` |
| 69 | +
|
| 70 | +* <!-- .element: class="fragment fade-in" --> Reference means the same object with the same properties |
| 71 | +* <!-- .element: class="fragment fade-in" --> Reference preserves cv-qualifiers (<code>const</code>, <code>volatile</code>) |
| 72 | +* <!-- .element: class="fragment fade-in" --> Copy drops cv-qualifiers |
| 73 | +* <!-- .element: class="fragment fade-in" --> Copy of array decays to a pointer |
| 74 | +
|
| 75 | +___ |
| 76 | +
|
| 77 | +### Function declaration with arrow |
| 78 | +
|
| 79 | +```cpp |
| 80 | +int sum(int a, int b); |
| 81 | +auto sum(int a, int b) -> int; |
| 82 | +
|
| 83 | +
|
| 84 | +auto isEven = [](int a) -> bool { |
| 85 | + return a % 2; |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +Introduced to allow definition of the type returned from lambda functions. |
| 90 | +<!-- .element: class="fragment fade-in" --> |
| 91 | + |
| 92 | +___ |
| 93 | +<!-- .slide: style="font-size: 0.9em" --> |
| 94 | + |
| 95 | +### Deduction of a function returned type |
| 96 | + |
| 97 | +```cpp |
| 98 | +auto multiply(int x, int y) { |
| 99 | + return x * y; |
| 100 | +} |
| 101 | + |
| 102 | +auto get_name(int id) { |
| 103 | + if (id == 1) |
| 104 | + return std::string("Gadget"); |
| 105 | + else if (id == 2) |
| 106 | + return std::string("SuperGadget"); |
| 107 | + return string("Unknown"); |
| 108 | +} |
| 109 | + |
| 110 | +auto factorial(int n) { |
| 111 | + if (n == 1) |
| 112 | + return 1; |
| 113 | + return factorial(n - 1) * n; |
| 114 | +} |
| 115 | +``` |
| 116 | +
|
| 117 | +* <!-- .element: class="fragment fade-in" --> Introduced in C++14 |
| 118 | +* <!-- .element: class="fragment fade-in" --> Deduction mechanism is the same as for deduction of variable types |
| 119 | +* <!-- .element: class="fragment fade-in" --> All <code>return</code> instructions must return the same type |
| 120 | +* <!-- .element: class="fragment fade-in" --> Recursion allowed only if recursive function call is not a first <code>return</code> statement |
| 121 | +
|
| 122 | +___ |
| 123 | +
|
| 124 | +## range-based for loop |
| 125 | +
|
| 126 | +```cpp |
| 127 | +std::vector<int> v = {0, 1, 2, 3, 4, 5}; |
| 128 | +
|
| 129 | +for (const auto & element : v) { |
| 130 | + std::cout << element << ' '; |
| 131 | +} |
| 132 | +std::cout << '\n'; |
| 133 | +``` |
| 134 | + |
| 135 | +___ |
| 136 | + |
| 137 | +### Generated code for-range based for loop |
| 138 | + |
| 139 | +```cpp |
| 140 | +{ |
| 141 | + auto && __range = range_expression ; |
| 142 | + auto __begin = begin_expr ; |
| 143 | + auto __end = end_expr ; |
| 144 | + for ( ; __begin != __end; ++__begin) { |
| 145 | + range_declaration = *__begin; |
| 146 | + loop_statement |
| 147 | + } |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +___ |
| 152 | +<!-- .slide: data-background="#cf802a" --> |
| 153 | + |
| 154 | +## Exercise |
| 155 | + |
| 156 | +Put auto wherever you think is good. |
| 157 | + |
| 158 | +Use range-based for loops wherever possible. |
| 159 | + |
| 160 | +### Let's have some fun :) |
| 161 | +<!-- .element: class="fragment fade-in" --> |
| 162 | + |
| 163 | +Connect to my VSC and edit my program simultaneously. |
| 164 | +<!-- .element: class="fragment fade-in" --> |
0 commit comments