Peter-Van-Weert-BeC17-Part-I.pptx
- Количество слайдов: 111
17 Part I – The Core Language
“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 • 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. ” • 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
Nested Namespaces
Nested Namespaces namespace Nikon { namespace Metrology { namespace Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector
Nested Namespaces namespace Nikon { namespace Metrology { namespace Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector
Nested Namespaces namespace Nikon { namespace Metrology { namespace Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector
Nested Namespaces in C++17 namespace Nikon: : Metrology: : Point. Clouds { struct Point { double x, y, z; }; typedef std: : vector
static_assert(expression)
static_assert recap (C++11) struct Point { double x, y, z; }; typedef std: : vector
static_assert recap (C++11) struct Point { double x, y, z; }; typedef std: : vector
static_assert recap (C++11) struct Point { double x, y, z; virtual double Norm(); }; typedef std: : vector
static_assert in C++17 struct Point { double x, y, z; virtual double Norm(); }; typedef std: : vector
Structured Bindings
std: : tuple quick recap (C++11) std: : tuple
std: : tuple quick recap (C++11) std: : tuple
std: : tuple quick recap (C++11) std: : tuple
Structured Bindings (C++17) std: : tuple
Structured 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
Structured 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
Structured 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
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] Case 2: valid std: : tuple_size
Custom Structured Bindings /* Case 2: valid std: : tuple_size
Custom Structured Bindings /* Case 2: let T = decltype(expr), and std: : tuple_size
Custom Structured Bindings /* Case 2: let T = decltype(expr), and std: : tuple_size
Custom Structured Bindings /* Case 2: let T = decltype(expr), and std: : tuple_size
Custom Structured Bindings /* Case 2: let T = decltype(expr), and std: : tuple_size
Custom Structured Bindings /* Case 2: let T = decltype(expr), and std: : tuple_size
Custom Structured Bindings /* Case 2: let T = decltype(expr), and std: : tuple_size
Initializers for if & switch
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; //. . . if (widget = Gimme. Widget()) { //. . . Did you mean “widget == Gimme. Widget()”? } } // widget cannot be used here. . .
Assign-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); 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); 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, val); success){ process(*iter); } else { FATAL("Duplicate"); } // iter or success cannot be used here. . .
Initializers: Other Use Cases /* Locks */ if (std: : lock_guard
Initializers for Switches switch (auto widget = Gimme. Widget(); widget->Get. Phalangy()) { case 123: /* widget can be used here as well. . . */ } switch (std: : lock_guard
constexpr if
constexpr 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
Example 1: recursive pack unpacking template
Example 2: std: : enable_if / SFINAE template
Example 2: std: : enable_if / SFINAE template
Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template
Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template
Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template
Example 3: Specializations of (Member) Template Functions /* Custom structured bindings. . . */ namespace Nikon { class Point { /*. . . */ template
Fold Expressions
Folds over Parameter Packs auto sum() { return 0; } template
Fold Expression template
Fold Expressions (pack . . . ) pack 0 (. . . (packn-1 packn)) (. . . pack) ((pack 0 pack 1) . . . ) packn (pack . . . val) pack 0 (. . . (packn-1 (packn val))) (val . . . pack) (((val pack 0) pack 1) . . . ) packn With one of + - * / % ^ & | << >> += -= *= /= %= ^= &= |= <<= >>= = == != < > <= >= && || , . * ->*
Fold Expressions (pack . . . ) pack 0 (. . . (packn-1 packn)) (. . . pack) ((pack 0 pack 1) . . . ) packn (pack . . . val) pack 0 (. . . (packn-1 (packn val))) (val . . . pack) (((val pack 0) pack 1) . . . ) packn With one of + - * / % ^ & | << >> += -= *= /= %= ^= &= |= <<= >>= = == != < > <= >= && || , . * ->*
Fold Expressions: operator , template
Right Fold with operator , template
Left Fold with operator << template
Template Argument Deduction for Constructors
Examples (Before) std: : pair
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++17
Explicit Deduction Guides namespace std { template
Explicit Deduction Guides namespace std { template
Capture *this
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this // Asynchronously execute f(args) template
Lambdas: Capture *this class Foo { int m_bar; public: void lish(); // foofaraw (fo o′fə-rô): a fuss over something trivial std: : function
Attributes • Attributes for namespaces and enumerators • [[fallthrough]], [[nodiscard]], [[maybe_unused]] • using for attributes (namespaces)
Attributes recap (C++11 / C++14) • [[noreturn]] void Raise. Hell(); void Raise. Hell() { throw Hell(); }; • [[deprecated]] class [[deprecated]] Foo {}; struct Bar { [[deprecated]] int m_abas; } [[deprecated("Use Raise. Hell() instead")]] void Raise. Inferno(); • [[carries_dependency]]
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: 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]] 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(); 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… }
[[nodiscard]] • Why does std: : async() become synchronous? typedef int write the /*. . . */ using type traits? • How to errorcode; errorcodedeclare using && (perfect forwarding)? • Why Do. Something(); errorcode Do. Something. Else(); template
[[nodiscard]] typedef int 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]] // [[nodiscard]] on class, enum, or function declaration enum [[nodiscard]] errorcode; errorcode Do. Something(); errorcode Do. Something. Else(); template
[[nodiscard]] enum [[nodiscard]] errorcode; errorcode Do. Something(); errorcode Do. Something. Else(); template
[[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 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]] 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, 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)]] 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)]] 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
Guaranteed Copy Elision • 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 T f() { return T{}; // no copy here (C++17) } T x = f(); T g() { T t; return t; } // no copy here either (C++17) // copy may be elided but not guaranteed
auto x{expr} int a = 1; int b(2); int c{3}; (C++11 / C++14) auto d = 1; auto e(2); auto f{3}; #define ASSERT_TYPE(EXPR, T) static_assert(std: : is_same
auto x{expr} int a = 1; int b(2); int c{3}; (C++17) auto d = 1; auto e(2); auto f{3}; #define ASSERT_TYPE(EXPR, T) static_assert(std: : is_same
f( auto_ptr
Refined Expression Evaluation Order (C++17) 1. 2. 3. 4. 5. 6. 7. 8. 9. a. b a->*b a(bi, bj, bk) b=a b @= a a[b] a << b a >> b
f( auto_ptr
C++17 Language Changes
Seen 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 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(
Features Removed from C++17 • register keyword ▫ Reserved for future use • ++ operator for bool • Trigraphs ▫ ? ? = # ? ? / ? ? ’ ^ ? ? ( [ ? ? ! |. . .
- PART II - THE C++ STANDARD LIBRARY
“Vocabulary Types” • std: : optional
Containers • try_emplace() and insert_or_assign() • Splicing for associative containers ▫ Move nodes between containers ▫ Merge whole containers • Non-const data() for strings • 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: : 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_guard
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 management tools • Special math functions ▫ Bessel, Neumann, Legendre, hypergeometric, . . . • Type traits ▫ trait_v
Find 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/whatare-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. . .