482 114 12MB
English Pages [600] Year 2021
C++20 Rainer Grimm This book is for sale at http://leanpub.com/c20 This version was published on 2021-08-28
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. © 2020 - 2021 Rainer Grimm
Contents Reader Testimonials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction . . . . . . . . . . . . . . Conventions . . . . . . . . . . . . Special Fonts . . . . . . . . . Special Boxes . . . . . . . . Source Code . . . . . . . . . . . . Compilation of the Programs How should you read the Book? . . Personal Notes . . . . . . . . . . . Acknowledgments . . . . . . About Me . . . . . . . . . .
About C++
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
i
. . . . . . . . . .
ii ii ii iii iii iii v v v vi
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Historical Context 1.1 C++98 . . . 1.2 C++03 . . . 1.3 TR1 . . . . . 1.4 C++11 . . . 1.5 C++14 . . . 1.6 C++17 . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
2 2 2 3 3 3 3
2. Standardization 2.1 Stage 3 . . 2.2 Stage 2 . . 2.3 Stage 1 . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
4 4 5 5
. . . . . . . . . . . . . . . . . . . . . . . .
6
3. C++20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
. . . .
A Quick Overview of C++20
CONTENTS
3.1
3.2
3.3
3.4
The Big Four . . . . . . . . . . . . . . . . . 3.1.1 Concepts . . . . . . . . . . . . . . 3.1.2 Modules . . . . . . . . . . . . . . 3.1.3 The Ranges Library . . . . . . . . 3.1.4 Coroutines . . . . . . . . . . . . . Core Language . . . . . . . . . . . . . . . . 3.2.1 Three-Way Comparison Operator . 3.2.2 Designated Initialization . . . . . . 3.2.3 consteval and constinit . . . . . 3.2.4 Template Improvements . . . . . . 3.2.5 Lambda Improvements . . . . . . 3.2.6 New Attributes . . . . . . . . . . . The Standard Library . . . . . . . . . . . . 3.3.1 std::span . . . . . . . . . . . . . . 3.3.2 Container Improvements . . . . . 3.3.3 Arithmetic Utilities . . . . . . . . 3.3.4 Formatting Library . . . . . . . . 3.3.5 Calendar and Time Zones . . . . . Concurrency . . . . . . . . . . . . . . . . . 3.4.1 Atomics . . . . . . . . . . . . . . 3.4.2 Semaphores . . . . . . . . . . . . 3.4.3 Latches and Barriers . . . . . . . . 3.4.4 Cooperative Interruption . . . . . 3.4.5 std::jthread . . . . . . . . . . . . 3.4.6 Synchronized Outputstreams . . .
The Details
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
8 8 9 10 11 13 13 13 16 17 18 18 19 19 20 20 20 21 23 23 24 24 25 26 28
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
4. Core Language . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Concepts . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Two Wrong Approaches . . . . . . . . . . . . 4.1.2 Advantages of Concepts . . . . . . . . . . . . 4.1.3 The long, long History . . . . . . . . . . . . . 4.1.4 Use of Concepts . . . . . . . . . . . . . . . . 4.1.5 Constrained and Unconstrained Placeholders 4.1.6 Abbreviated Function Templates . . . . . . . 4.1.7 Predefined Concepts . . . . . . . . . . . . . . 4.1.8 Define Concepts . . . . . . . . . . . . . . . . 4.1.9 Requires Expressions . . . . . . . . . . . . . 4.1.10 User-Defined Concepts . . . . . . . . . . . . 4.2 Modules . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Why do we need Modules? . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
32 33 33 40 40 41 53 55 59 67 74 78 91 91
CONTENTS
4.3
4.4 4.5
4.6 4.7
4.8
4.9
4.2.2 Advantages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3 A First Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.4 Compiler Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5 Export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.6 Guidelines for a Module Structure . . . . . . . . . . . . . . . . . . . . . . . 4.2.7 Module Interface Unit and Module Implementation Unit . . . . . . . . . . . 4.2.8 Private Module Fragment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.9 Submodules and Module Partitions . . . . . . . . . . . . . . . . . . . . . . . 4.2.10 Templates in Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.11 Module Linkage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.12 Header Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Equality Comparison and Three-Way Comparison . . . . . . . . . . . . . . . . . . . 4.3.1 Comparison before C++20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 Comparison since C++20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.3 Comparison Categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.4 Compiler-Generated Equality and Spaceship Operator . . . . . . . . . . . . 4.3.5 Rewriting Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.6 User-Defined and Auto-Generated Comparison Operators . . . . . . . . . . Designated Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.1 Aggregate Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.2 Named Initialization of Class Members . . . . . . . . . . . . . . . . . . . . . consteval and constinit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5.1 consteval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5.2 constinit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5.3 Comparison of const, constexpr, consteval, and constinit . . . . . . . . . . 4.5.4 Solving the Static Initialization Order Fiasco . . . . . . . . . . . . . . . . . . Template Improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.1 Conditionally Explicit Constructor . . . . . . . . . . . . . . . . . . . . . . . 4.6.2 Non-Type Template Parameters (NTTP) . . . . . . . . . . . . . . . . . . . . Lambda Improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.7.1 Template Parameter for Lambdas . . . . . . . . . . . . . . . . . . . . . . . . 4.7.2 Detection of the Implicit Copy of the this Pointer . . . . . . . . . . . . . . . 4.7.3 Lambdas in an Unevaluated Context and Stateless Lambdas can be DefaultConstructed and Copy-Assigned . . . . . . . . . . . . . . . . . . . . . . . . 4.7.4 Pack Expansion in Init-Capture . . . . . . . . . . . . . . . . . . . . . . . . . New Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8.1 [[nodiscard("reason")]] . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8.2 [[likely]] and [[unlikely]] . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8.3 [[no_unique_address]] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Further Improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.9.1 volatile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.9.2 Range-based for loop with Initializers . . . . . . . . . . . . . . . . . . . . . 4.9.3 Virtual constexpr function . . . . . . . . . . . . . . . . . . . . . . . . . . .
98 98 101 109 110 112 115 116 121 124 126 130 130 132 136 140 144 148 150 150 151 157 157 159 160 163 169 169 172 177 177 181 183 187 191 192 197 198 201 201 203 204
CONTENTS
4.9.4 4.9.5 4.9.6
The new Character Type of UTF-8 Strings: char8_t . . . . . . . . . . . . . . 205 in Local Scopes . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Default Member Initializers for Bit Fields . . . . . . . . . . . . . . . . . . . 208
using enum
5. The Standard Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 The Ranges Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.2 Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.3 Direct on the Container . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.4 Function Composition . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.5 Lazy Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.6 Define a View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.7 A Flavor of Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 std::span . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.1 Static versus Dynamic Extent . . . . . . . . . . . . . . . . . . . . . . 5.2.2 Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.3 Automatically Deduces the Size of a Contiguous Sequence of Objects 5.2.4 Modifying the Referenced Objects . . . . . . . . . . . . . . . . . . . 5.2.5 Addressing std::span Elements . . . . . . . . . . . . . . . . . . . . . 5.2.6 A Constant Range of Modifiable Elements . . . . . . . . . . . . . . . 5.2.7 Dangers of std::span . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Container and Algorithm Improvements . . . . . . . . . . . . . . . . . . . . . 5.3.1 constexpr Containers and Algorithms . . . . . . . . . . . . . . . . . 5.3.2 std::array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.3 Consistent Container Erasure . . . . . . . . . . . . . . . . . . . . . . 5.3.4 contains for Associative Containers . . . . . . . . . . . . . . . . . . 5.3.5 Shift the Content of a Container . . . . . . . . . . . . . . . . . . . . 5.3.6 String prefix and suffix checking . . . . . . . . . . . . . . . . . . . . 5.4 Arithmetic Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Safe Comparison of Integers . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 Mathematical Constants . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.3 Midpoint and Linear Interpolation . . . . . . . . . . . . . . . . . . . 5.4.4 Bit Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5 Formatting Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 Format String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 User-Defined Types . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6 Calendar and Time Zones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.1 Basic Chrono Terminology . . . . . . . . . . . . . . . . . . . . . . . 5.6.2 Basic Types and Literals . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.3 Time of day . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.4 Calendar Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.5 Time Zones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.6 Chrono I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
210 211 212 215 218 223 225 229 232 239 239 241 246 247 249 251 253 256 256 259 261 265 268 270 273 273 278 280 283 289 291 300 306 307 308 315 318 339 346
CONTENTS
5.7
Further Improvements . . . . . . . . . 5.7.1 std::bind_front . . . . . . . 5.7.2 std::is_constant_evaluated 5.7.3 std::source_location . . . . 5.7.4 std::to_address . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
361 361 363 365 366
6. Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Coroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 A Generator Function . . . . . . . . . . . . . . . . . 6.1.2 Characteristics . . . . . . . . . . . . . . . . . . . . . 6.1.3 The Framework . . . . . . . . . . . . . . . . . . . . 6.1.4 Awaitables and Awaiters . . . . . . . . . . . . . . . 6.1.5 The Workflows . . . . . . . . . . . . . . . . . . . . . 6.1.6 co_return . . . . . . . . . . . . . . . . . . . . . . . . 6.1.7 co_yield . . . . . . . . . . . . . . . . . . . . . . . . 6.1.8 co_await . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Atomics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 std::atomic_ref . . . . . . . . . . . . . . . . . . . . 6.2.2 Atomic Smart Pointer . . . . . . . . . . . . . . . . . 6.2.3 std::atomic_flag Extensions . . . . . . . . . . . . . 6.2.4 std::atomic Extensions . . . . . . . . . . . . . . . . 6.3 Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4 Latches and Barriers . . . . . . . . . . . . . . . . . . . . . . . 6.4.1 std::latch . . . . . . . . . . . . . . . . . . . . . . . 6.4.2 std::barrier . . . . . . . . . . . . . . . . . . . . . . 6.5 Cooperative Interruption . . . . . . . . . . . . . . . . . . . . 6.5.1 std::stop_source . . . . . . . . . . . . . . . . . . . 6.5.2 std::stop_token . . . . . . . . . . . . . . . . . . . . 6.5.3 std::stop_callback . . . . . . . . . . . . . . . . . . 6.5.4 A General Mechanism to Send Signals . . . . . . . . 6.5.5 Joining Threads . . . . . . . . . . . . . . . . . . . . 6.5.6 New wait Overloads for the condition_variable_any 6.6 std::jthread . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.1 Automatically Joining . . . . . . . . . . . . . . . . . 6.6.2 Cooperative Interruption of a std::jthread . . . . . 6.7 Synchronized Output Streams . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
368 369 370 373 375 378 382 385 386 390 398 398 406 410 418 422 427 427 432 437 438 439 440 443 445 446 450 451 453 456
7. Case Studies . . . . . . . . . . . . . . 7.1 Fast Synchronization of Threads 7.1.1 Condition Variables . . 7.1.2 std::atomic_flag . . . 7.1.3 std::atomic . . . 7.1.4 Semaphores . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
465 466 467 469 473 475
. . . . . .
. . . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . .
. . . . . .
. . . . . .
CONTENTS
7.2 7.3 7.4
7.1.5 All Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . Variations of Futures . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.1 A Lazy Future . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.2 Execution on Another Thread . . . . . . . . . . . . . . . . . Modification and Generalization of a Generator . . . . . . . . . . . . 7.3.1 Modifications . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.2 Generalization . . . . . . . . . . . . . . . . . . . . . . . . . Various Job Workflows . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.1 The Transparent Awaiter Workflow . . . . . . . . . . . . . 7.4.2 Automatically Resuming the Awaiter . . . . . . . . . . . . . 7.4.3 Automatically Resuming the Awaiter on a Separate Thread .
Epilogue
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
477 478 480 484 489 493 496 500 500 503 506
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
Further Information
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
8. C++23 and Beyond . . . . . . . . . . . . . . . . . . . . . 8.1 C++23 . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 The Coroutines Library . . . . . . . . . . . 8.1.2 Modularized Standard Library for Modules 8.1.3 Executors . . . . . . . . . . . . . . . . . . . 8.1.4 The Network Library . . . . . . . . . . . . 8.2 C++23 or Later . . . . . . . . . . . . . . . . . . . . . 8.2.1 Contracts . . . . . . . . . . . . . . . . . . . 8.2.2 Reflection . . . . . . . . . . . . . . . . . . 8.2.3 Pattern Matching . . . . . . . . . . . . . . 8.3 Further Information about C++23 . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
514 515 515 530 533 538 540 540 544 548 550
9. Feature Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551 10. Glossary . . . . . . . . . . . . . . 10.1 Aggregate . . . . . . . . . . 10.2 Automatic Storage Duration 10.3 Callable . . . . . . . . . . . 10.4 Callable Unit . . . . . . . . . 10.5 Concurrency . . . . . . . . . 10.6 Critical Section . . . . . . . 10.7 Data Race . . . . . . . . . . 10.8 Deadlock . . . . . . . . . . . 10.9 Dynamic Storage Duration . 10.10 Eager Evaluation . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
563 563 563 563 563 563 564 564 564 564 564
CONTENTS
10.11 10.12 10.13 10.14 10.15 10.16 10.17 10.18 10.19 10.20 10.21 10.22 10.23 10.24 10.25 10.26 10.27 10.28 10.29 10.30 10.31 10.32 10.33 10.34 10.35 10.36 10.37 10.38 10.39 10.40 10.41 10.42
Executor . . . . . . . . . Function Objects . . . . . Lambda Expressions . . . Lazy Evaluation . . . . . Literal Type . . . . . . . Lock-free . . . . . . . . . Lost Wakeup . . . . . . . Math Laws . . . . . . . . Memory Location . . . . Memory Model . . . . . Non-blocking . . . . . . Object . . . . . . . . . . Parallelism . . . . . . . . POD (Plain Old Data) . . Predicate . . . . . . . . . RAII . . . . . . . . . . . Race Conditions . . . . . Regular Type . . . . . . . Scalar Type . . . . . . . . SemiRegular . . . . . . . Short-Circuit Evaluation Standard-Layout Type . . Static Storage Duration . Spurious Wakeup . . . . The Big Four . . . . . . . The Big Six . . . . . . . . Thread . . . . . . . . . . Thread Storage Duration Time Complexity . . . . Translation Unit . . . . . Trivial Type . . . . . . . Undefined Behavior . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
564 565 565 566 566 566 566 566 567 567 567 567 567 567 567 568 568 568 568 568 568 569 569 569 569 570 570 570 570 570 571 571
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
Reader Testimonials Sandor Dargo
Senior Software Development Engineer at Amadeus
”’C++ 20: Get the details’ is exactly the book you need right now if you want to immerse yourself in the latest version of C++. It’s a complete guide, Rainer doesn’t only discuss the flagship features of C++20, but also every minor addition to the language. Luckily, the book includes tons of example code, so even if you don’t have direct access yet to the latest compilers, you will have a very good idea of what you can expect from the different features. A highly recommended read!”
Adrian Tam
Director of Data Science, Synechron Inc.
”C++ has evolved a lot from its birth. With C++20, it is like a new language now. Surely this book is not a primer to teach you inheritance or overloading, but if you need to bring your C++ knowledge up to date, this is the right book. You will be surprised about the new features C++20 brought into C++. This book gives you clear explanations with concise examples. Its organization allows you to use it as a reference later. It can help you unleash the old language into its powerful future.”
Introduction My book C++20 is both a tutorial and a reference. It teaches you C++20 and provides you with the details of this new thrilling C++ standard. The thrill factor is mainly due to the big four of C++20: • Concepts change the way we think about and program with templates. They are semantic categories for template parameters. They enable you to express your intention directly in the type system. If something goes wrong, the compiler gives you a clear error message. • Modules overcome the restrictions of header files. They promise a lot. For example, the separation of header and source files becomes as obsolete as the preprocessor. In the end, we have faster build times and an easier way to build packages. • The new ranges library supports performing algorithms directly on the containers, composing algorithms with the pipe symbol, and applying algorithms lazily on infinite data streams. • Thanks to coroutines, asynchronous programming in C++ becomes mainstream. Coroutines are the basis for cooperative tasks, event loops, infinite data streams, or pipelines. Of course, this is not the end of the story. Here are more C++20 features: • • • • • • • •
Auto-generated comparison operators Calendar and time-zone libraries Format library Views on contiguous memory blocks Improved, interruptible threads Atomic smart pointers Semaphores Coordination primitives such as latches and barriers
Conventions Here are only a few conventions.
Special Fonts Italic: I use Italic to emphasize a quote. Bold: I use Bold to emphasize a name. Monospace:
I use Monospace for code, instructions, keywords, and names of types, variables, functions, and classes.
iii
Introduction
Special Boxes Boxes contain background tips, warnings, and distilled information.
Tip Headline This box provides additional information about the presented material and tips for compiling the programs.
Warning Headline Warning boxes should help you to avoid pitfalls.
Distilled Information This box summarizes at the end of each main section the important things to remember.
Source Code The source code examples–starting with the details part–shown in the book are complete. That means, assuming you have a conforming compiler, you can compile and run them. I put the name of the source file in the title of each source code example. The source code uses four whitespaces for indentation. Only for layout reasons, I sometimes use two whitespaces. Furthermore, I’m not a fan of namespace directives such as using namespace std because they make the code more difficult to read and pollute namespaces. Consequently, I use them only when it improves the code’s readability (e.g.: using namespaces std::chrono_literals or using namespace std::chrono). When necessary for layout reasons, I indent two characters instead of four, and I apply using directives such as using std::chrono::Monday. Using directives allows it to use the names unqualified: constexpr auto monday = Monday instead of constexpr auto monday = std::chrono::Monday.
Compilation of the Programs As the C++20 standard is brand-new, many examples can only be compiled and executed with a specific compiler. I use the newest GCC¹, Clang², and MSVC³ compilers. When you compile the ¹https://gcc.gnu.org/ ²https://clang.llvm.org/ ³https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B
iv
Introduction
program, you must specify the applied C++ standard. This means, with GCC or Clang you must provide the flag -std=c++20, and with MSVC /std:c++latest. When using concurrency features, unlike with MSVC, the GCC and Clang compilers require that you link the pthread library using -pthread. If you don’t have an appropriate C++ compiler at your disposal, use an online compiler such as Wandbox⁴ or Compiler Explorer⁵. When you use Compiler Explorer with GCC or Clang, you can also execute the program. First, you have to enable Run the compiled output (1) and, second, open the Output window (2).
Run code in the Compiler Explorer
You can get more details about the C++20 conformity of various C++ compilers at cppreference.com⁶. ⁴https://wandbox.org/ ⁵https://godbolt.org/ ⁶https://en.cppreference.com/w/cpp/compiler_support
Introduction
v
How should you read the Book? If you are not familiar with C++20, start at the very beginning with a quick overview to get the big picture. Once you get the big picture, you can proceed with the core language. The presentation of each feature should be self-contained, but reading the book from the beginning to the end would be the preferable way. On first reading, you can skip the features not mentioned in the quick overview chapter.
Personal Notes Acknowledgments I started a request for proofreading on my English blog: ModernesCpp Cpp⁷ and received more responses than I expected. Special thanks to all of you. Here are the names of the proofreaders in alphabetic order: Bob Bird, Nicola Bombace, Dave Burchill, Sandor Dargo, James Drobina, Frank Grimm, Kilian Henneberger, Ivan “espkk” Kondakov, Péter Kardos, Rakesh Mane, Jonathan O’Connor, John Plaice, Iwan Smith, Paul Targosz, Steve Vinoski, and Greg Wagner. Special thanks also to my daughter Juliette, and my wife Beatrix. Juliette improved my wording and fixed many of my typos. Beatrix created Cippi and illustrated the book. Cippi Let me introduce Cippi. Cippi will accompany you in this book. I hope, you like her. ⁷http://www.modernescpp.com
vi
Introduction
I’m Cippi, the C ++ Pippi Longstocking: curious, clever and - yes - feminine!
About Me I’ve worked as a software architect, team lead, and instructor since 1999. In 2002, I created companyintern meetings for further education. I have given training courses since 2002. My first tutorials were about proprietary management software, but I began teaching Python and C++ soon after. In my spare time, I like to write articles about C++, Python, and Haskell. I also like to speak at conferences. I publish weekly on my English blog Modernes Cpp⁸ and the German blog⁹, hosted by Heise Developer. Since 2016, I have been an independent instructor giving seminars about modern C++ and Python. I have published several books in various languages about modern C++ and, in particular, about concurrency. Due to my profession, I always search for the best way to teach modern C++. ⁸https://www.modernescpp.com/ ⁹https://www.grimm-jaud.de/index.php/blog
vii
Introduction
Rainer Grimm
About C++
1. Historical Context C++20 is the next big C++ standard after C++11. Like C++11, C++20 changes the way we program in modern C++. This change mainly results from the addition of Concepts, Modules, Ranges, and Coroutines to the language. To understand this next big step in the evolution of C++, let me write a few words about the historical context of C++20.
C++ History
C++ is about 40 years old. Here is a brief overview of what has changed in the previous years.
1.1 C++98 At the end of the 80’s, Bjarne Stroustrup and Margaret A. Ellis wrote their famous book Annotated C++ Reference Manual ¹(ARM). This book served two purposes, to define the functionality of C++ in a world with many implementations, and to provide the basis for the first C++ standard C++98 (ISO/IEC 14882). Some of the essential features of C++98 were: templates, the Standard Template Library (STL) with its containers, and algorithms, strings, and IO streams.
1.2 C++03 With C++03 (14882:2003), C++98 received a technical correction, so small that there is no place on the timeline above. In the community, C++03, which includes C++98, is called legacy C++. ¹https://www.stroustrup.com/arm.html
Historical Context
3
1.3 TR1 In 2005, something exciting happened. The so-called Technical Teport 1 (TR1) was published. TR1 was a big step toward C++11 and, therefore, towards Modern C++. TR1 (TR 19768) is based on the Boost project², which was founded by members of the C++ standardization committee. TR1 had 13 libraries that were destined to become part of the C++11 standard. For example, the regular expression library, the random number library, smart pointers and hashtables. Only the so-called special mathematical functions had to wait until C++17.
1.4 C++11 We call the C++11 standard Modern C++. The name Modern C++ is also used for C++14 and C++17. C++11 introduced many features that fundamentally changed the way we program in C++. For example, C++11 had the additions of TR1, but also move semantics, perfect forwarding, variadic templates, and constexpr. But that was not all. With C++11, we also got, for the first time, a memory model as the fundamental basis of threading and the standardization of a threading API.
1.5 C++14 C++14 is a small C++ standard. It brought read-writer locks, generalized lambdas, and extended constexpr functions.
1.6 C++17 C++17 is neither a big nor a small C++ standard. It has two outstanding features: the parallel STL and the standardized filesystem API. About 80 algorithms of the Standard Template Library can be executed in parallel or vectorized. As with C++11, the boost libraries were highly influential for C++17. Boost provided the filesystem library and new data types: std::string_view, std::optional, std::variant, and std::any.
²https://www.boost.org/
2. Standardization The C++ standardization process is democratic. The committee is called WG21 (Working Group 21) and was formed in 1990-91. The officers of WG 21 are: • Convener: chairs the WG21, sets the meeting schedule, and appoints Study Groups • Project Editor: applies changes to the working draft of the C++ standard • Secretary: assigns minutes of the WG21 meetings The image shows you the various subgroups and Study Groups of the committee.
Study groups in the C++ standardization process
The committee is organized into a three-stage pipeline consisting of several subgroups. SG stands for Study Group.
2.1 Stage 3 Stage 3 for the wording and the change proposal’s consistency have two groups: core language wording (CWG) and library wording (LWG).
Standardization
5
2.2 Stage 2 Stage 2 has two groups: core language evolution (EWG) and library evolution (LEWG). EWG and LEWG are responsible for new features that involve language and standard library extensions, respectively.
2.3 Stage 1 Stage 1 aims for domain-specific investigation and incubation. The study groups’ members meet in face-to-face meetings, between the meeting by telephone or video conferences. Central groups may review the work of the study groups to ensure consistency. These are the domain-specific Study Groups: • SG1, Concurrency: Concurrency and parallelism topics, including the memory model • SG2, Modules: Modules-related topics • SG3, File System • SG4, Networking: Networking library development • SG5, Transactional Memory: Transactional memory constructs for future addition • SG6, Numerics: Numerics topics such as fixed-point numbers, floating-point numbers, and fractions • SG7, Compile time programming: compile time programming in general • SG8, Concepts • SG9, Ranges • SG10, Feature Test: Portable checks to test whether a particular C++ supports a specific feature • SG11, Databases: Database-related library interfaces • SG12, UB & Vulnerabilities: Improvements against vulnerabilities and undefined/unspecified behavior in the standard • SG13, HMI & I/O (Human/Machine Interface): Support for output and input devices • SG14, Game Development & Low Latency: Game developers and (other) low-latency programming requirements • SG15, Tooling: Developer tools, including modules and packages • SG16, Unicode: Unicode text processing in C++ • SG17, EWG Incubator: Early discussion about the core language evolution • SG18, LEWG Incubator: Early discussions about the library language evolution • SG19, Machine Learning: Artificial intelligence (AI) specific topics but also linear algebra • SG20, Education: Guidance for modern course materials for C++ education • SG21, Contracts: Language support for Design by Contract • SG22, C/C++ Liaison: Discussion of C and C++ coordination This section provided you a concise overview of the standardization in C++ and, in particular, the C++ committee. You can find more details about the standardization on https://isocpp.org/std¹. ¹https://isocpp.org/std
A Quick Overview of C++20
3. C++20 Before I dive into the details of C++20, I want to give a quick overview of the features in C++20. This overview should serve two purposes; to give a first impression, and to provide links to the relevant sections you can use to dive directly into the details. Consequently, this chapter has only code snippets, but no complete programs. My book starts with a short historical detour into the previous C++ standards. This detour provides context when comparing C++20 to previous revisions and demonstrates the importance of C++20 by providing a historical context.
C++20 has four outstanding features: concepts, ranges, coroutines, and modules. Each deserves its own subsection.
C++20
8
3.1 The Big Four
Each feature of the Big Four changes the way we program in modern C++. Let me start with concepts.
3.1.1 Concepts Generic programming with templates enables it to define functions and classes which can be used with various types. As a result, it is not uncommon that you instantiate a template with the wrong type. The result can be many pages of cryptic error messages. This problem ends with concepts. Concepts empower you to write requirements for template parameters that are checked by the compiler, and revolutionize the way we think about and write generic code. Here is why: • Requirements for template parameters become part of their public interface. • The overloading of functions or specializations of class templates can be based on concepts. • We get improved error messages because the compiler checks the defined template parameter requirements against the given template arguments. Additionally, this is not the end of the story. • You can use predefined concepts or define your own. • The usage of auto and concepts is unified. Instead of auto, you can use a concept. • If a function declaration uses a concept, it automatically becomes a function template. Writing function templates is, therefore, as easy as writing a function. The following code snippet demonstrates the definition and the use of the straightforward concept Integral:
C++20
9
Definition and use of the Integral concept template concept Integral = std::is_integral::value; Integral auto gcd(Integral auto a, Integral auto b) { if( b == 0 ) return a; else return gcd(b, a % b); }
The Integral concept requires from its type parameter T that std::is_integral::value be true. std::is_integral::value is a value from the type traits library¹ checking at compile time if T is integral. If std::is_integral::value evaluates to true, all is fine; otherwise, you get a compiletime error. The gcd algorithm determines the greatest common divisor based on the Euclidean² algorithm. The code uses the so-called abbreviated function template syntax to define gcd. Here, gcd requires that its arguments and return type support the concept Integral. In other words, gcd is a kind of function template that puts requirements on its arguments and return value. When I remove the syntactic sugar, you can see the real nature of gcd. Here is the semantically equivalent gcd algorithm, using a requires clause. Use of the concept Integral in the requires clause template requires Integral T gcd(T a, T b) { if( b == 0 ) return a; else return gcd(b, a % b); }
The requires clause states the requirements on the type parameters of gcd.
3.1.2 Modules Modules promise a lot: • Faster compile times • Reduce the need to define macros • Express the logical structure of the code • Make header files obsolete • Get rid of ugly macro workarounds Here is the first simple math module: ¹https://en.cppreference.com/w/cpp/header/type_traits ²https://en.wikipedia.org/wiki/Euclid
C++20
10
The math module 1
export module math;
2 3 4 5
export int add(int fir, int sec) { return fir + sec; }
The expression export module math (line 1) is the module declaration. Putting export before the function add (line 3) exports the function. Now, it can be used by a consumer of the module. Use of the math module import math; int main() { add(2000, 20); }
The expression import math imports the math module and makes the exported names visible in the current scope.
3.1.3 The Ranges Library The ranges library supports algorithms which • can operate directly on containers; you don’t need iterators to specify a range • can be evaluated lazily • can be composed To make it short: The ranges library supports functional patterns. The following example demonstrates function composition using the pipe symbol.
C++20
11
Function composition with the pipe symbol 1 2 3 4
int main() { std::vector ints{0, 1, 2, 3, 4, 5}; auto even = [](int i){ return i % 2 == 0; }; auto square = [](int i) { return i * i; };
5
for (int i : ints | std::views::filter(even) | std::views::transform(square)) { std::cout