trainings/AdvancedCppV2/Presentation/moder_cpp_cpp17_small_features.md

244 lines
6.4 KiB
Markdown

## Nested namespace definitions
<!-- .slide: data-background="#ccc" -->
You can nest namespaces like this:
<!-- .element: class="fragment fade-in" -->
```c++
namespace A::B::C {
...
}
```
<!-- .element: class="fragment fade-in" -->
Instead of this:
<!-- .element: class="fragment fade-in" -->
```c++
namespace A {
namespace B {
namespace C {
...
}
}
}
```
<!-- .element: class="fragment fade-in" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Class template argument deduction
From C++17 class template arguments can be deduced automatically. Automatic template argument deduction was available earlier only for template functions.
```c++
std::pair p(1, 'x'); // C++17: OK, C++14: error: missing.
// std::pair<int, char>
std::pair<int, std::string> p(1, "x"); // C++14: OK
// std::pair<int, std::string>
auto p2 = std::make_pair(1, "x"); // C++17: OK, C++14: OK (but not string!)
// std::pair<int, const char*>
std::pair p3(1, "x"); // C++17: OK (but not string!), C++14 error
```
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Selection statements with initializer (1)
New versions of the `if` and `switch` statements for C++:
<!-- .element: class="fragment fade-in" -->
### `if (init; condition)`
<!-- .element: class="fragment fade-in" -->
```cpp
status_code foo() { // C++14
{ //variable c scope
status_code c = bar();
if (c != SUCCESS) {
return c;
}
}
// ...
}
```
<!-- .element: class="fragment fade-in" -->
```cpp
status_code foo() { // C++17
if (status_code c = bar(); c != SUCCESS) {
return c;
}
// ...
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.8em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Selection statements with initializer (2)
### `switch (init; condition)`
<!-- .element: class="fragment fade-in" -->
```C++
class Foo {
public:
enum class ErrorCode {
Ok,
Bad,
VeryBad
};
ErrorCode doSth() {}
}
int main() {
switch (Foo foo ; const auto err = foo.doSth()) {
case ErrorCode::Ok:
break;
case ErrorCode::Bad:
break;
case ErrorCode::VeryBad:
break;
}
}
```
<!-- .slide: style="font-size: 0.85em" -->
<!-- .element: class="fragment fade-in" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Selection statements with initializer (3)
```C++
class ThreadSafeQueue {
public:
std::optional<int> try_pop() {
int val = 0;
// Lock guard is visible inside if-else
if (std::lock_guard lock(m_) ; queue_.empty()) {
return {};
} else {
val = queue_.front();
queue_.pop();
}
// Here mutex is no longer locked
logger << "pop value from queue";
return val;
}
private:
std::queue<int> queue_;
std::mutex m_;
};
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.92em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Hiding variable inside <code>if-else</code> statement (2)
We can avoid assigning iterators and then comapre it in `if` statement. Now we can write it faster
```C++
int main() {
std::vector<int> vec;
if (const auto it = std::find(std::cbegin(vec), std::cend(vec), 10) ; it != std::cend(vec)) {
// *it* is visible here
} else {
// and here
}
// but not here
std::map<std::string, int>
if (const auto it = map.find("Ala") ; it != std::cend(map)) {
// ...
} else {
// ...
}
}
```
<!-- .slide: style="font-size: 0.79em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Unified initialization
* <!-- .element: class="fragment fade-in" --> C++11 introduce <code>{}</code> for initialization
* <!-- .element: class="fragment fade-in" --> C++17 fixed some problems with <code>{}</code> and unified it.
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Unified initialization C++11
* Guess output (compiler 4.7.4 with C++11 flag)
<pre><code class="cpp" data-trim data-line-numbers data-noescape>
auto a {1}; <span class="fragment">//std::initializer_list&lt;int></span>
auto b = {1}; <span class="fragment">//std::initializer_list&lt;int></span>
auto c {1, 2}; <span class="fragment">//std::initializer_list&lt;int></span>
auto d = {1, 2}; <span class="fragment">//std::initializer_list&lt;int></span>
auto e = {1, 2, 3.f}; <span class="fragment">//Not compile </span>
auto f {1, 2, 3.f} <span class="fragment">//Not compile </span>
</code></pre>
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Unified initialization C++17
* Guess output (compiler 8.4 with C++17 flag)
<pre><code class="cpp" data-trim data-line-numbers data-noescape>
auto a {1}; <span class="fragment">//int </span>
auto b = {1}; <span class="fragment">//std::initializer_list&lt;int></span>
auto c {1, 2}; <span class="fragment">//Not compile (mising =) </span>
auto d = {1, 2}; <span class="fragment">//std::initializer_list&lt;int></span>
auto e = {1, 2, 3.f}; <span class="fragment">//Not compile </span>
auto f {1, 2, 3.f} <span class="fragment">//Not compile </span>
</code></pre>
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->
## Structural biding
* <!-- .element: class="fragment fade-in" --> Unpack strucures, classes, tuples, pairs etc...
```C++
struct Foo{};
std::tuple<int, std::string, Foo> getTuple() {
return {5, "Ala has a cat", Foo{}};
}
struct Bar {
std::string str_;
double val_;
char c_;
std::vector<int> vec_;
};
int main() {
const auto& [id, topic, foo] = getTuple();
std::vector<Bar> bar;
for (const auto& [name, value, sign, vec] : bar) {
// ...
}
std::map<int, std::string> map;
for (const auto& [key, value] : map) {
// ..
}
};
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.70em" -->