## Nested namespace definitions You can nest namespaces like this: ```c++ namespace A::B::C { ... } ``` Instead of this: ```c++ namespace A { namespace B { namespace C { ... } } } ``` ___ ## 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 std::pair p(1, "x"); // C++14: OK // std::pair auto p2 = std::make_pair(1, "x"); // C++17: OK, C++14: OK (but not string!) // std::pair std::pair p3(1, "x"); // C++17: OK (but not string!), C++14 error ``` ___ ## Selection statements with initializer (1) New versions of the `if` and `switch` statements for C++: ### `if (init; condition)` ```cpp status_code foo() { // C++14 { //variable c scope status_code c = bar(); if (c != SUCCESS) { return c; } } // ... } ``` ```cpp status_code foo() { // C++17 if (status_code c = bar(); c != SUCCESS) { return c; } // ... } ``` ___ ## Selection statements with initializer (2) ### `switch (init; condition)` ```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; } } ``` ___ ## Selection statements with initializer (3) ```C++ class ThreadSafeQueue { public: std::optional 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 queue_; std::mutex m_; }; ``` ___ ## Hiding variable inside if-else 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 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 if (const auto it = map.find("Ala") ; it != std::cend(map)) { // ... } else { // ... } } ``` ___ ## Unified initialization * C++11 introduce {} for initialization * C++17 fixed some problems with {} and unified it. ___ ## Unified initialization C++11 * Guess output (compiler 4.7.4 with C++11 flag)

auto a {1};             //std::initializer_list<int>
auto b = {1};           //std::initializer_list<int>
auto c {1, 2};          //std::initializer_list<int>
auto d = {1, 2};        //std::initializer_list<int>
auto e = {1, 2, 3.f};   //Not compile               
auto f {1, 2, 3.f}      //Not compile               
___ ## Unified initialization C++17 * Guess output (compiler 8.4 with C++17 flag)

auto a {1};             //int                       
auto b = {1};           //std::initializer_list<int>
auto c {1, 2};          //Not compile (mising =)              
auto d = {1, 2};        //std::initializer_list<int>
auto e = {1, 2, 3.f};   //Not compile               
auto f {1, 2, 3.f}      //Not compile               
___ ## Structural biding * Unpack strucures, classes, tuples, pairs etc... ```C++ struct Foo{}; std::tuple getTuple() { return {5, "Ala has a cat", Foo{}}; } struct Bar { std::string str_; double val_; char c_; std::vector vec_; }; int main() { const auto& [id, topic, foo] = getTuple(); std::vector bar; for (const auto& [name, value, sign, vec] : bar) { // ... } std::map map; for (const auto& [key, value] : map) { // .. } }; ```