17 Part I – The Core Language

Скачать презентацию 17 Part I – The Core Language Скачать презентацию 17 Part I – The Core Language

peter-van-weert-bec17-part-i.pptx

  • Размер: 2.8 Мб
  • Автор:
  • Количество слайдов: 111

Описание презентации 17 Part I – The Core Language по слайдам

17 Part I – The Core Language   17 Part I – The Core Language

“ I'm a bit sad about that. [. . . ] A lot of“ I’m a bit sad about that. [. . . ] A lot of minor improvements can add up to something significant. Most of these will help somebody in some way. There’s something for everybody here. I can’t imagine any C++ programmer that will not have at least some relieve from pain in C++17. That will not be able to write some piece of their code better in C++17. ” – Bjarne Stroustrup , Cpp. Con 2016 keynote

Shameless Self-Promotion Ahead     Shameless Self-Promotion Ahead

Shameless Self-Promotion • Co-author: Marc Gregoire • Concise reference (212 pages) • Complete C++14Shameless Self-Promotion • Co-author: Marc Gregoire • Concise reference (212 pages) • Complete C++14 Standard Library “ Very useful quick reference for C++ programmers on some part of the library they have forgotten or in need of a quick refresh. ” “ Even the most experienced C++ programmer will learn a thing or two from the book and find it an indispensable reference and memory aid. ”

Overview “ A lot of minor improvements can add up to something significant. ”Overview “ A lot of minor improvements can add up to something significant. ” • Part I – The C++ Core Language ▫ Today: more detail ▫ Next year: quick overview • Part II – The C++ Standard Library ▫ Today: quick overview ▫ Next year: more detail

- PART I – THE C++ CORE LANGUAGE     — PART I – THE C++ CORE LANGUAG

Nested Namespaces     Nested Namespaces

namespace Nikon { namespace Metrology { namespace Point. Clouds { struct  Point {namespace Nikon { namespace Metrology { namespace Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector Cloud ; } } }Nested Namespaces

namespace Nikon { namespace Metrology { namespace  Point. Clouds { struct  Pointnamespace Nikon { namespace Metrology { namespace Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector Cloud ; }}}Nested Namespaces

namespace Nikon { namespace Metrology { namespace Point. Clouds { struct  Point {namespace Nikon { namespace Metrology { namespace Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector Cloud ; }}}Nested Namespaces

namespace Nikon: : Metrology: : Point. Clouds { struct  Point { double x,namespace Nikon: : Metrology: : Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector Cloud ; }Nested Namespaces in C++

static_assert(expressi on)     static_assert(expressi on)

static_assert recap (C++11) struct  Point { double x, y, z; }; typedef std:static_assert recap (C++11) struct Point { double x, y, z; }; typedef std: : vector Cloud ; static_assert ( sizeof ( Point ) == 3 * sizeof ( double ), «Unexpected Point size» ) ; static_assert ( is_trivially_copyable : : value, «Point is not trivially copyable» ) ; • Type traits? • When is_trivially_copyable ? (check w. safe to memcpy() etc. ) • is_pod ? is_trivial ? . . .

static_assert recap (C++11) struct  Point { double x, y, z; }; typedef std:static_assert recap (C++11) struct Point { double x, y, z; }; typedef std: : vector Cloud ; static_assert ( sizeof ( Point ) == 3 * sizeof ( double ), «Unexpected Point size» ) ; static_assert ( is_trivially_copyable : : value, «Point is not trivially copyable» ) ;

struct  Point { double x, y, z;  virtual  double  Norm();struct Point { double x, y, z; virtual double Norm(); }; typedef std: : vector Cloud ; static_assert ( sizeof ( Point ) == 3 * sizeof ( double ), «Unexpected Point size» ) ; static_assert ( is_trivially_copyable : : value, «Cloud is not trivially copyable» ) ; static_assert recap (C++11) Static assertion failed with “Cloud is not trivially coyable”Static assertion failed with “Unexpected Point size”

struct  Point { double x, y, z;  virtual  double  Norm();struct Point { double x, y, z; virtual double Norm(); }; typedef std: : vector Cloud ; static_assert ( sizeof ( Point ) == 3 * sizeof ( double )) ; static_assert ( is_trivially_copyable : : value) ; static_assert in C++17 Static assertion failed: is_trivially_copyable: : value. Static assertion failed: sizeof(Point) == 3 * sizeof(double)

Structured Bindings     Structured Bindings

std: : tuple quick recap (C+ +11) std: : tuple  int , std:std: : tuple quick recap (C+ +11) std: : tuple triple() ; auto t = tripple(); auto & x = std: : get(t); auto & y = std: : get(t); // C++14 auto & z = std: : get(t);

std: : tuple quick recap (C+ +11) std: : tuple  int , std:std: : tuple quick recap (C+ +11) std: : tuple triple() ; int x, z; string y; std: : tie(x, y, z) = tripple(); • std: tuple ? • std: : tie() ? • Tip: tie() for operator< ?

std: : tuple quick recap (C+ +11) std: : tuple  int , std:std: : tuple quick recap (C+ +11) std: : tuple triple() ; int x, z; string y; // Declare std: : tie(x, y, z) = tripple(); // Tie

Structured Bindings (C++17) std: : tuple  int , std: : string , Structured Bindings (C++17) std: : tuple tripple() ; auto [x, y, z] = tripple(); // Declare and tie!

Structured Bindings /* Case 1: C-style arrays -- expr [ i ] */ intStructured Bindings /* Case 1: C-style arrays —> expr [ i ] */ int array[3] { 1, 2, 3 }; auto [one, two, three] = array; /* Case 2: valid std: : tuple_size: : value —> expr. get() or get( expr ) (ADL) */ std: : tuple t ; auto [x, y, z] = t; // Also: std: : array std: : array abc{ ‘a’ , ‘b’ , ‘c’ }; auto [a, b, c] = abc;

Structured Bindings /* Case 3: all non-static members are public */ // Typical forStructured Bindings /* Case 3: all non-static members are public */ // Typical for C-style structs struct Point { double m_x, m_y, m_z; }; Point point { 0, 0, 0 }; auto [x, y, z] = point; // Also: std: : pair! std: : map map; auto [iter, success] = map. insert( «Answer» , 42); for ( const auto & [key, value] : map) { /*. . . */ }

Structured Bindings /* Case 3: all non-static members are public */ // Typical forStructured Bindings /* Case 3: all non-static members are public */ // Typical for C-style structs struct Point { double m_x, m_y, m_z; }; Point point { 0, 0, 0 }; auto [x, y, z] = point; // Also: std: : pair! std: : map map; auto [iter, success] = map. insert( «Answer» , 42); for ( const auto & [key, value] : map) { /*. . . */ }

Structured Bindings Q&A • Move or copy?  Move! • ‘ auto [a, b]Structured Bindings Q&A • Move or copy? Move! • ‘ auto [a, b] = {1, «two» } ’? Not yet. . . • ‘ [x, y, z] = tripple()’? Not yet: use tie(). . . • ‘ auto [&a, const b] =. . . ’? No. • ‘ string [a, b ] =. . . ’? No. • ‘ auto [a, string b ] =. . . ’? No. • ‘ auto [x, std: : ignore, z] =. . . ’? Not yet: anticipate pattern matching (like _ or * ) • ‘ auto [x, [a, b], z] =. . . ’? Not yet. . .

Custom Structured Bindings /* Case 1: C-style arrays -- expr [ i ] CaseCustom Structured Bindings /* Case 1: C-style arrays —> expr [ i ] Case 2: valid std: : tuple_size: : value —> expr. get() or get( expr ) (ADL) Case 3: all non-static members are public */ namespace Nikon { class Point { private : double m_x, m_y, m_z; public : double X() const ; double Y() const ; double Z() const ; }; }

Custom Structured Bindings /* Case 2: valid std: : tuple_sizedecltype( expr ): : valueCustom Structured Bindings /* Case 2: valid std: : tuple_size: : value —> expr. get() or get( expr ) (ADL) */ namespace std { template struct tuple_size : public integral_constant {}; }

Custom Structured Bindings /* Case 2: let T = decltype( expr ), and Custom Structured Bindings /* Case 2: let T = decltype( expr ), and std: : tuple_size: : value is valid —> std: : tuple_element: : type = expr. get() or std: : tuple_element: : type = get( expr ) (ADL) */ namespace std { template struct tuple_size : public integral_constant {}; template struct tuple_element { using type = double ; }; template struct tuple_element { using type = double ; }; template struct tuple_element { using type = double ; }; }

Custom Structured Bindings /* Case 2: let T = decltype( expr ), and Custom Structured Bindings /* Case 2: let T = decltype( expr ), and std: : tuple_size: : value is valid —> std: : tuple_element: : type = expr. get() or std: : tuple_element: : type = get( expr ) (ADL) */ namespace Nikon { class Point ; template auto get( const Point &) = delete ; template auto get( const Point & p) { return p. X(); }; template auto get( const Point & p) { return p. Y(); }; template auto get( const Point & p) { return p. Z(); }; }

Custom Structured Bindings /* Case 2: let T = decltype( expr ), and Custom Structured Bindings /* Case 2: let T = decltype( expr ), and std: : tuple_size: : value is valid —> std: : tuple_element: : type = expr. get() or std: : tuple_element: : type = get( expr ) (ADL) */ namespace Nikon { class Point ; template auto get( const Point &) = delete ; template auto get( const Point & p) { return p. X(); }; template auto get( const Point & p) { return p. Y(); }; template auto get( const Point & p) { return p. Z(); }; }

Custom Structured Bindings /* Case 2: let T = decltype( expr ), and Custom Structured Bindings /* Case 2: let T = decltype( expr ), and std: : tuple_size: : value is valid —> std: : tuple_element: : type = expr. get() or std: : tuple_element: : type = get( expr ) (ADL) */ namespace Nikon { class Point { /*. . . */ template auto get() const = delete ; template auto get() const { return p. X(); }; template auto get() const { return p. Y(); }; template auto get() const { return p. Z(); }; }; } Explicit specialization in non-namespace scope ‘class Point’

Custom Structured Bindings /* Case 2: let T = decltype( expr ), and Custom Structured Bindings /* Case 2: let T = decltype( expr ), and std: : tuple_size: : value is valid —> std: : tuple_element: : type = expr. get() or std: : tuple_element: : type = get( expr ) (ADL) */ namespace Nikon { class Point { /*. . . */ template auto get() = { return get(std: : integral_constant ()); }; private : auto get(std: : integral_constant ) { return m_x; } auto get(std: : integral_constant ) { return m_y; } auto get(std: : integral_constant ) { return m_z; } }; }

Custom Structured Bindings /* Case 2: let T = decltype( expr ), and Custom Structured Bindings /* Case 2: let T = decltype( expr ), and std: : tuple_size: : value is valid —> std: : tuple_element: : type = expr. get() or std: : tuple_element: : type = get( expr ) (ADL) */ namespace std { /*. . . */ } namespace Nikon { class Point { /*. . . */ }; } Nikon: : Point p; /*. . . */ auto [x, y, z] = p;

Initializers for if & switch     Initializers for if & switch

Declare-and-null-check Idiom Widget * Gimme. Widget(); if ( auto widget = Gimme. Widget()) {Declare-and-null-check Idiom Widget * Gimme. Widget(); if ( auto widget = Gimme. Widget()) { // widget can be used in this scope. . . } // widget cannot be user here. . .

Assign-and-null-check Idiom Widget * Gimme. Widget(); { Widget * widget; //. . . ifAssign-and-null-check Idiom Widget * Gimme. Widget(); { Widget * widget; //. . . if (widget = Gimme. Widget()) { //. . . } } // widget cannot be used here. . . Did you mean “widget == Gimme. Widget()”?

Assign-and-null-check Idiom Widget * Gimme. Widget(); { Widget * widget; //. . . ifAssign-and-null-check Idiom Widget * Gimme. Widget(); { Widget * widget; //. . . if ((widget = Gimme. Widget())) { //. . . } } // widget cannot be used here. . .

Checks Different from Null-checks?  (Before) { auto result = map. insert(key, val); Checks Different from Null-checks? (Before) { auto result = map. insert(key, val); if (result. second) { process(*result. first); } else { FATAL( «Duplicate» ); } } // result cannot be used here. . .

Other Checks: Initializers (C+ +17) if ( auto result = map. insert(key, val); Other Checks: Initializers (C+ +17) if ( auto result = map. insert(key, val); result. second) { process(*result. first); } else { FATAL( «Duplicate» ); } // result cannot be used here. . .

Or of course. . . (C++17) if ( auto [iter, success] = map. insert(key,Or of course. . . (C++17) if ( auto [iter, success] = map. insert(key, val); success){ process(*iter); } else { FATAL( «Duplicate» ); } // iter or success cannot be used here. . .

Initializers: Other Use Cases /* Locks */ if (std: : lock_guard std: : mutexInitializers: Other Use Cases /* Locks */ if (std: : lock_guard lock; shared_vec. empty()) { shared_vec. push_back(42); } /* Local variable(s) for output parameter(s) */ if (Widget w; Get. Widgets(&w)) { process(w); } if (Widget w 1, w 2; Get. Widgets(&w 1, &w 2)){ process(w 1); process(w 2); }

Initializers for Switches switch ( auto widget = Gimme. Widget();  widget-Get. Phalangy()) {Initializers for Switches switch ( auto widget = Gimme. Widget(); widget->Get. Phalangy()) { case 123: /* widget can be used here as well. . . */ } switch (std: : lock_guard lock; shared_val) { case 123: /*. . . */ }

constexpr if     constexpr if

constexpr if • Written ‘ if  constexpr ( expression ) ’ • Staticallyconstexpr if • Written ‘ if constexpr ( expression ) ’ • Statically evaluated during template instantiation ▫ In other words: expression must be a constexpr • One of the branches is discarded ▫ Does not discard static_assert() s • Easier and more readable than multiple overloads or template specializations, SFINAE, . . .

Example 1: recursive pack unpacking template  typename  Single  void Print( SingleExample 1: recursive pack unpacking template void Print( Single && value) { std: : cout << value << std: : endl; } template void Print( Head && head, Tail &&. . . tail) { Print(head); Print(tail. . . ); } Print(123, «123» , 1. 23);

Example 1: recursive pack unpacking template  typename  Head ,  typename. .Example 1: recursive pack unpacking template Print( Head && head, Tail &&. . . tail) { std: : cout << head << std: : endl; if constexpr ( sizeof. . . (tail)) { Print(std: : forward(tail). . . ); } } Print(123, «123» , 1. 23);

Example 2:  std: : enable_if / SFINAE template  typename  T Example 2: std: : enable_if / SFINAE template std: : enable_if_t<std: : is_integral : : value> Handle( T && value) { Handle. Integral. Value(std: : forward(value)); } template std: : enable_if_t<!std: : is_integral : : value> Handle( T && value) { Handle. Any. Other. Value(std: : forward(value)); } • Type traits? • std: : enable_if ( _t )? • SFINAE ?

Example 2:  std: : enable_if / SFINAE template  typename  T Example 2: std: : enable_if / SFINAE template void Handle( T && value) { if constexpr (std: : is_integral : : value) Handle. Integral. Value(std: : forward(value)); else Handle. Any. Other. Value(std: : forward(value)); }

Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template auto get() = { return get(std: : integral_constant ()); }; private : auto get(std: : integral_constant ) { return m_x; } auto get(std: : integral_constant ) { return m_y; } auto get(std: : integral_constant ) { return m_z; } }; }

Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template auto get() { if constexpr (I == 0) { return m_x; } if constexpr (I == 1) { return m_y; } if constexpr (I == 2) { return m_z; } } }; }

Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template auto get() { if constexpr (I == 0) { return m_x; } else if constexpr (I == 1) { return m_y; } else if constexpr (I == 2) { return m_z; } else static_assert ( false ); } }; }

Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template auto get() { static_assert (I < 3); if constexpr (I == 0) { return m_x; } if constexpr (I == 1) { return m_y; } if constexpr (I == 2) { return m_z; } }; }

Fold Expressions     Fold Expressions

Folds over Parameter Packs auto sum() { return 0; } template  typename Folds over Parameter Packs auto sum() { return 0; } template auto sum( const Head & head, const Tail &. . . tail) { return head + sum(tail. . . ); } std: : cout << sum(1, 2. 0, 3) << std: : endl; // 6.

Fold Expression template  typename. . .  T  void sum( const Fold Expression template void sum( const T &. . . values) { return ( values +. . . ); }

Fold Expressions (pack . . . ) pack 0 (. . . ( packFold Expressions (pack . . . ) pack 0 (. . . ( pack n-1 pack n )) (. . . pack) (( pack 0 pack 1 ) . . . ) pack n (pack . . . val) pack 0 (. . . ( pack n-1 ( pack n val ))) (val . . . pack) ((( val pack 0 ) pack 1 ) . . . ) pack n With one of + — * /  % ^ &  | <> += -= *= /= %= ^= &= |= <>= = == !=  = && || , . * ->*

Fold Expressions (pack . . . ) pack 0 (. . . ( packFold Expressions (pack . . . ) pack 0 (. . . ( pack n-1 pack n )) (. . . pack) (( pack 0 pack 1 ) . . . ) pack n (pack . . . val) pack 0 (. . . ( pack n-1 ( pack n val ))) (val . . . pack) ((( val pack 0 ) pack 1 ) . . . ) pack n With one of + — * /  % ^ &  | <> += -= *= /= %= ^= &= |= <>= = == !=  = && || , . * ->*

Fold Expressions: operator , template  typename  Single  void Print( const Fold Expressions: operator , template void Print( const Single & value) { std: : cout << value << " " ; } template void Print( const Head & head, const Tail &. . . tail) { Print(head); Print(tail. . . ); } Print(123, «123» , 1. 23); // 123 1.

Right Fold with operator , template  typename  Single  void Print( constRight Fold with operator , template void Print( const Single & value) { std: : cout << value << " " ; } template void Print( const Pack &. . . pack) { (Print(pack), . . . ); } Print(123, «123» , 1. 23); // 123 1.

Left Fold with operator  template  typename. . .  Pack  voidLeft Fold with operator << template void Print( const Pack &. . . pack) { (std: : cout <<. . . << pack); } Print(123, "123" , 1. 23); // 1231231.

Template Argument Deduction for Constructors     Template Argument Deduction for Constructors

Examples (Before) std: : pair  int ,  double  p(2, 4. 5);Examples (Before) std: : pair p(2, 4. 5); auto t = std: : make_tuple(4, 3, 2. 5); std: : copy(a, a+3, std: : back_inserter(v)); // Virtually impossible to pass a lambda to a template // class’ constructor without declaring the lambda for_each(begin(v), end(v), Foo ([&]( int i) { })); std: : lock_guard lck(foo. m_mutex); std: : lock_guard <std: : mutex , // New in C+ +17 std: : unique_lock > lck 2(foo. m_mutex, ul);

Examples (C++17) std: : pair p(2, 4. 5); std: : tuple t(4, 3, 2.Examples (C++17) std: : pair p(2, 4. 5); std: : tuple t(4, 3, 2. 5); std: : copy(a, a+3, std: : back_insert_iterator(v)); // Now easy instead of virtually impossible to pass a // lambda to a template class’ constructor. . . for_each(begin(v), end(v), Foo ([&]( int i) { })); auto lck = std: : lock_guard (foo. m_mutex); std: : lock_guard lck 2(foo. m_mutex, ul); // New in C+ +

Explicit Deduction Guides namespace s td { template  typename  T  classExplicit Deduction Guides namespace s td { template class vector { /*. . . */ }; } auto v = std: : vector (3, ‘x’ ); // std: : vector? ? ?

Explicit Deduction Guides namespace s td { template  typename  T  classExplicit Deduction Guides namespace s td { template class vector { /*. . . */ }; template vector ( int , T ) -> vector ; } auto v = std: : vector (3, ‘x’ ); // std: : vector!

Capture *this     Capture *this

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) { std: : thread (std: : forward( f ), std: : forward( args ). . . ). detach(); } • Why detach() ? • Why not std: : async() ? • What is perfect forwarding?

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) ; class Foo { int m_bar; public : void lish() { int bar = 123; Fire. And. Forget([=] { cout << bar << endl; }); } };

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) ; class Foo { int m_bar; public : void lish() { int bar = 123; Fire. And. Forget([=] { cout << bar + m_bar << endl; }); } }; { Foo foo; foo. lish(); }

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) ; class Foo { int m_bar; public : void lish() { int bar = 123; Fire. And. Forget([=, m_bar=m_bar] // C++14 { cout << bar + m_bar << endl; }); } };

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) ; class Foo { int m_bar; public : void lish() { int bar = 123; Fire. And. Forget([=, copy=m_bar] // C++14 { cout << bar + copy << endl; }); } };

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) ; class Foo { int m_bar; public : void lish() { int bar = 123; Fire. And. Forget([=, copy=* this ] // C++14 { cout << bar + copy. m_bar << endl; }); } };

Lambdas: Capture *this // Asynchronously execute f(args) template  typename  Function , Lambdas: Capture *this // Asynchronously execute f(args) template void Fire. And. Forget( Function && f , Args &&. . . args ) ; class Foo { int m_bar; public : void lish() { int bar = 123; Fire. And. Forget([=, * this ] // C++17 { cout << bar + m_bar << endl; }); } };

Lambdas: Capture *this class  Foo  { int m_bar; public : void lish()Lambdas: Capture *this class Foo { int m_bar; public : void lish() ; std: : function faraw() { return [* this ]( int i) { return m_bar + i; }; } }; // foofaraw (f o′fə-rô): a fuss over something oo trivial

Attributes • Attributes for namespaces and enumerators • [[fallthrough]] ,  [[nodiscard]] , Attributes • Attributes for namespaces and enumerators • [[fallthrough]] , [[nodiscard]] , [[maybe_unused]] • using for attributes (namespaces)

Attributes recap (C++11 / C++14) • [[noreturn]] • [[deprecated]] • [[carries_dependency]] [[noreturn]] void Raise.Attributes recap (C++11 / C++14) • [[noreturn]] • [[deprecated]] • [[carries_dependency]] [[noreturn]] void Raise. Hell(); void Raise. Hell() { throw Hell(); }; class [[deprecated]] Foo {}; struct Bar { [[deprecated]] int m_abas; } [[deprecated(«Use Raise. Hell() instead»)]] void Raise. Inferno();

Attributes for namespaces and enumerators (C++17) namespace [[deprecated]] Legacy. Stuff { /*. . .Attributes for namespaces and enumerators (C++17) namespace [[deprecated]] Legacy. Stuff { /*. . . */ }; namespace [[deprecated]] { /*. . . */ }; enum [[deprecated]] Legacy. Enum; // Possible since C+ +14 enum Error. Code { catastrofic , faulty , flawed [[deprecated(«Use ‘faulty’ instead»)]] , iffy , okayish , peachy , hunkydory [[deprecated(«Use ‘peachy’ instead»)]] }

[[fallthrough]] switch (number) { case 111: case 222: Do. Something(); break ; case 333:[[fallthrough]] switch (number) { case 111: case 222: Do. Something(); break ; case 333: Do. Something. Else(); case 444: Do. Some. More(); break ; // Continued to the right… default : assert( false ); case 555: if (Should. I()) Do. Something(); else { Do. Something. Else(); break ; } case 666: Raise. Hell(); case 777: Do. Something. Different(); }

[[fallthrough]] switch (number) { case 111: case 222: Do. Something(); break ; case 333:[[fallthrough]] switch (number) { case 111: case 222: Do. Something(); break ; case 333: Do. Something. Else(); [[fallthrough]] ; case 444: Do. Some. More(); break ; // Continued to the right… default : assert( false ); [[fallthrough]] ; case 555: if (Should. I()) { Do. Something(); [[fallthrough]] ; } else { Do. Something. Else(); break ; } case 666: Raise. Hell(); case 777: Do. Something. Different(); }

[[nodiscard]] typedef int errorcode ; errorcode Do. Something(); errorcode Do. Something. Else(); template [[nodiscard]] typedef int errorcode ; errorcode Do. Something(); errorcode Do. Something. Else(); template std: : future async( Function &&, Args &&. . . ); void main() { async( [] { Do. Something(); } ); Do. Something. Else(); std: : cout << "Did it!" << std: : endl ; } • Why does std: : async() become synchronous? • How to write the /*. . . */ using type traits? • Why declare using && (perfect forwarding)?

[[nodiscard]] typedef int errorcode ; [[nodiscard]] errorcode Do. Something(); [[nodiscard]] errorcode Do. Something. Else();[[nodiscard]] typedef int errorcode ; [[nodiscard]] errorcode Do. Something(); [[nodiscard]] errorcode Do. Something. Else(); template [[nodiscard]] std: : future async( F &&, Args &&. . . ); void main() { async( [] { Do. Something(); } ); Do. Something. Else(); std: : cout << "Did it!" << std: : endl ; }

[[nodiscard]] enum errorcode ; [[nodiscard]] errorcode Do. Something(); [[nodiscard]] errorcode Do. Something. Else(); template[[nodiscard]] enum errorcode ; [[nodiscard]] errorcode Do. Something(); [[nodiscard]] errorcode Do. Something. Else(); template [[nodiscard]] std: : future async( F &&, Args &&. . . ); void main() { async( [] { Do. Something(); } ); Do. Something. Else(); std: : cout << "Did it!" << std: : endl ; }

[[nodiscard]] // [[nodiscard]] on class, enum, or function declaration enum [[nodiscard]] errorcode ; errorcode[[nodiscard]] // [[nodiscard]] on class, enum, or function declaration enum [[nodiscard]] errorcode ; errorcode Do. Something(); errorcode Do. Something. Else(); template [[nodiscard]] std: : future async( F &&, Args &&. . . ); void main() { async( [] { Do. Something(); } ); Do. Something. Else(); std: : cout << "Did it!" << std: : endl ; }

[[nodiscard]] enum [[nodiscard]] errorcode ; errorcode Do. Something(); errorcode Do. Something. Else(); template [[nodiscard]] enum [[nodiscard]] errorcode ; errorcode Do. Something(); errorcode Do. Something. Else(); template [[nodiscard]] std: : future async( F &&, Args &&. . . ); void main() { auto future. Error = async([] { return Do. Something(); }); auto error = Do. Something. Else(); if (Is. Success(error) && Is. Success(future. Error. get())) std: : cout << "Did it! " << std: : endl ; }

[[maybe_unused]] [[nodiscard]] bool  Test. Success( errorcode ); errorcode Do. Something(); void log( errorcode[[maybe_unused]] [[nodiscard]] bool Test. Success( errorcode ); errorcode Do. Something(); void log( errorcode ec) { #ifdef _LOGGING if (!Test. Success(ec)) std: : err << "Epic Fail!\n" ; #endif } void main() { auto result = Do. Something(); assert (Test. Success(result)); }

[[maybe_unused]] [[nodiscard]] bool  Test. Success( errorcode ); errorcode Do. Something(); void log( errorcode[[maybe_unused]] [[nodiscard]] bool Test. Success( errorcode ); errorcode Do. Something(); void log( errorcode ec) { #ifdef _LOGGING if (!Test. Success(ec)) std: : err << "Epic Fail!\n" ; #endif } void main() { auto result = Do. Something(); assert (Test. Success(result)); }

[[maybe_unused]] [[maybe_unused, nodiscard]] bool  Test. Success( errorcode ); errorcode Do. Something(); void log([[maybe_unused]] [[maybe_unused, nodiscard]] bool Test. Success( errorcode ); errorcode Do. Something(); void log( [[maybe_unused]] errorcode ec) { #ifdef _LOGGING if (!Test. Success(ec)) std: : err << "Epic Fail!\n" ; #endif } void main() { [[maybe_unused]] auto result = Do. Something(); assert (Test. Success(result)); }

using for Attributes void f() { [[rpr: : pipeline(bound, 8, blocking), rpr: : stream(A,using for Attributes void f() { [[rpr: : pipeline(bound, 8, blocking), rpr: : stream(A, B)]] for ( int i = 0; i < iterations ; ++i) { [[rpr: : kernel, rpr: : out(a), rpr: : target(cpu)]] a = get_value(); [[rpr: : kernel, rpr: : farm(4, ordered), rpr: : in(A, C), rpr: : out(A, B), rpr: : target(cpu, gpu)]] for ( int j = 0; j < max; ++j) b = f(a, c ); [[rpr: : kernel, rpr: : in(A, B)]] g(a, b); }}

using for Attributes void f() { [[ using rpr: pipeline(bound, 8, blocking), stream(A, B)]]using for Attributes void f() { [[ using rpr: pipeline(bound, 8, blocking), stream(A, B)]] for ( int i = 0; i < iterations ; ++i) { [[ using rpr: kernel, out(a), target(cpu)]] a = get_value(); [[ using rpr: kernel, farm(4, ordered), in(A, C), out(A, B), target(cpu, gpu)]] for ( int j = 0; j < max; ++j) b = f(a, c ); [[ using rpr: kernel, in(A, B)]] g(a, b); }}

using for Attributes void f() { [[ using rpr: pipeline(bound, 8, blocking), stream(A, B)]]using for Attributes void f() { [[ using rpr: pipeline(bound, 8, blocking), stream(A, B)]] for ( int i = 0; i < iterations ; ++i) { [[ using rpr: kernel, out(a), target(cpu)]] [[deprecated]] a = get_value(); [[ using rpr: kernel, farm(4, ordered), in(A, C), out(A, B), target(cpu, gpu)]] for ( int j = 0; j < max; ++j) b = f(a, c ); [[ using rpr: kernel, in(A, B)]] g(a, b); }}

Changes to Semantics     Changes to Semantics

Guaranteed Copy Elision T f() {  return  T {};  // noGuaranteed Copy Elision T f() { return T {}; // no copy here (C++17) } T x = f(); // no copy here either (C++17) T g() { T t; return t; // copy may be elided but not guaranteed } • When a temporary object is used to initialize another object • Including the object returned by a function, or the exception object created by a throw-expression

auto x{ expr } (C++11 / C+ +14) int a = 1; auto dauto x{ expr } (C++11 / C+ +14) int a = 1; auto d = 1; int b(2); auto e(2); int c{3}; auto f{3}; #define ASSERT_TYPE (EXPR, T) \ static_assert (std: : is_same : : value) ASSERT_TYPE (a, int ); ASSERT_TYPE (d, int ); ASSERT_TYPE (b, int ); ASSERT_TYPE (e, int ); ASSERT_TYPE (c, int ); // But! ASSERT_TYPE (f, std: : initializer_list );

auto x{ expr } (C++17) int a = 1; auto d = 1; intauto x{ expr } (C++17) int a = 1; auto d = 1; int b(2); auto e(2); int c{3}; auto f{3}; #define ASSERT_TYPE (EXPR, T) \ static_assert (std: : is_same : : value) ASSERT_TYPE (a, int ); ASSERT_TYPE (d, int ); ASSERT_TYPE (b, int ); ASSERT_TYPE (e, int ); ASSERT_TYPE (c, int ); ASSERT_TYPE (f, int );

Undefined Evaluation Order (before) std: : map  int ,  int  m;Undefined Evaluation Order (before) std: : map m; m[0] = m. size(); // m[0] == 0 or m[0] == 1 int i = 3; m[i] = ++i; // m[3] == 4 or m[4] == 4 f( auto_ptr( new T 1 ), auto_ptr( new T 2 ) ); // Got. W 56 — potential leak: use make_unique (C++14)! f( unique_ptr ( new Foo ), unique_ptr ( new Bar )); // The C++ Programming Language, 4 th Edition (assertion possible) std: : string s = «but I have heard it works even if you don’t believe in it» ; s. replace(0, 4, «» ) . replace(s. find( «even» ), 4, «only» ) . replace(s. find( » don’t» ), 6, «» ); assert (s == «I have heard it works only if you believe in it» );

Refined Expression Evaluation Order (C++17) 1.  a. b 2.  a-b 3. Refined Expression Evaluation Order (C++17) 1. a. b 2. a->b 3. a->*b 4. a(b i , b j , b k ) 5. b = a 6. b @= a 7. a[b] 8. a <> b

Undefined Evaluation Order (C++17) std: : map  int ,  int  m;Undefined Evaluation Order (C++17) std: : map m; m[0] = m. size(); // m[0] == 0 int i = 3; m[i] = ++i; // m[4] == 4 f( auto_ptr( new T 1 ), auto_ptr( new T 2 ) ); // Got. W 56 — no leak! f( unique_ptr ( new Foo ), unique_ptr ( new Bar )); // The C++ Programming Language, 4 th Edition (never asserts) std: : string s = «but I have heard it works even if you don’t believe in it» ; s. replace(0, 4, «» ) . replace(s. find( «even» ), 4, «only» ) . replace(s. find( » don’t» ), 6, «» ); assert (s == «I have heard it works only if you believe in it» );

C++17 Language Changes     C++17 Language Changes

Seen Today • Nested namespaces • static_assert ( expr ) • for -like initializersSeen Today • Nested namespaces • static_assert ( expr ) • for -like initializers for if and switch • Structured bindings • Constexpr if • Fold expressions • Capture * this • Attributes • Changes to semantics

Also Added in C++17. . .  • Hexadecimal floating literals:  0 xAlso Added in C++17. . . • Hexadecimal floating literals: 0 x 3. ABCp-10 • UTF-8 character literals: u 8’U’ , u 8’T’ , u 8’F’ , u 8’8′ • Preprocessor test for existence of headers: #if __has_include ( ) • Type deduction for non-type template parameters E. g. template struct S; • constexpr lambdas • Dynamic memory allocation for over-aligned data • Inline variables (cf. inline funtions) • . . .

Features Removed from C+ +17 • register keyword ▫ Reserved for future use •Features Removed from C+ +17 • register keyword ▫ Reserved for future use • ++ operator for bool • Trigraphs ▫ ? ? = # ? ? / \ ? ? ’ ^ ? ? ( [ ? ? ! | . . .

- PART II - THE C++ STANDARD LIBRARY     — PART II — THE C++ STANDARD LIBRARY

“ Vocabulary Types” • std: : optional  T  ▫ Optional values •“ Vocabulary Types” • std: : optional ▫ Optional values • std: : variant ▫ Type safe unions • std: : any ▫ Type safe void * • std: : string_view ▫ Efficient OO algorithms (no copying!) that work on const std: : string & , C-style strings, literals, . . .

Containers • try_emplace() and insert_or_assign() • Splicing for associative containers ▫ Move nodes betweenContainers • try_emplace() and insert_or_assign() • Splicing for associative containers ▫ Move nodes between containers ▫ Merge whole containers • Non-const data() for string s • Non-member std: : size() , std: : empty() , std: : data() ▫ Cf. std: : begin() / end() • . . .

Algorithms • std: : search() ▫ Boyer-Moore and Boyer-Moore-Horspool substring search algorithms • std:Algorithms • std: : search() ▫ Boyer-Moore and Boyer-Moore-Horspool substring search algorithms • std: : sample() ▫ Random sampling from a range • std: : clamp() ▫ Clamping between min and max value • Parallelism TS 1 ▫ 69 parallel versions of existing algorithms ▫ New parallel reduce-like algorithm

Threading • std: : shared_mutex ▫ Multiple readers-single writer lock • std: : lock_guardMutexes.Threading • std: : shared_mutex ▫ Multiple readers-single writer lock • std: : lock_guard ▫ Alternative to std: : lock() • std: : hardware_*_interference_size ▫ Query cache-line size • . . .

File System TS • Standard file system API for C++ ▫ Absolute paths ▫File System TS • Standard file system API for C++ ▫ Absolute paths ▫ Relative paths ▫ Files and directories ▫ Links ▫ Creating ▫ Copying ▫ Renaming ▫. . .

More C++17 Standard Library. . .  • Smart pointer improvements • Memory managementMore C++17 Standard Library. . . • Smart pointer improvements • Memory management tools • Special math functions ▫ Bessel, Neumann, Legendre, hypergeometric, . . . • Type traits ▫ trait _v shorthand for trait : : value ▫ std: : void_t ▫ std: : conjunction , disjunction , and negation • Efficient, locale-independent parsing and formatting of integers and floating point numbers • . . .

Find out more?  • C++ Standards Committee Papers ▫ http: //www. open-std. org/jtcFind out more? • C++ Standards Committee Papers ▫ http: //www. open-std. org/jtc 1/sc 22/wg 21/docs/papers/ ▫ ‘ Adopted’ papers • Stack. Overflow ‘What are the new features in C++17? ’ ▫ http : // stackoverflow. com/questions/38060436/what-are-the- new-features-in-c 17/38060437#38060437 ▫ Warning: many outdated links • Sutter’s Mill ▫ https: // herbsutter. com ▫ ‘ Trip reports’ posts • Notes of this presentation. . .