Book: Programming with C++20 - Writing finished
A while ago, I announced that I was writing a book about C++20 (Programming with C++20 - Concepts, Coroutines, Ranges, and more). A lot of you have already purchased an early copy available on Leanpub. Thank you! While I haven't made much visible progress, I did well in the background.
Today I proudly tell you that I have finished the writing process! All chapters are written, making it around 340 pages. A couple of them are still out for review, so it will take some time until they will be available on Leanpub.
I made it just in time for my upcoming Programming with C++20 class at CppCon. Of course, a virtual class. You can still register and will get a complimentary copy of the book.
My next steps are
- incorporating all the feedback
- looking at all the code listings ensuring that they are nicely formatted
- creating the index
- adding some images
- preparing the paperback version for KDP
This is how the final table of contents most likely will look like (unless your feedback leads to a change):
- 1 Concepts: Predicates for strongly typed generic code
- 1.1 Programming before Concepts
- 1.1.1 The
enable_if
requirement - 1.1.2 Long error messages from template errors
- 1.1.1 The
- 1.2 What are Concepts
- 1.2.1 Thinking in concepts
- 1.2.2 Concepts and types
- 1.3 The anatomy of a concept
- 1.4 Existing Concepts
- 1.5 The requires-clause: The runway for Concepts
- 1.6 The requires-expression
- 1.6.1 Simple requirement
- 1.6.2 Nested requirement
- 1.6.3 Compound requirement
- 1.6.4 Type requirement
- 1.6.5 Complete constrained version of
add
- 1.7 Adding Concepts to make requirements reusable
- 1.8 Testing requirements
- 1.9 Using a Concept
- 1.9.1 Using a
constexpr
function in a concept - 1.9.2 Applying a concept with a requires-clause
- 1.9.3 Applying a concept with a trailing requires-clause
- 1.9.4 Applying a concept as a type-constraint
- 1.9.1 Using a
- 1.10 Abbreviated function template with
auto
as generic parameter- 1.10.1 What does such a construct do?
- 1.10.2 Exemplary use case: Requiring a parameter type to be an invocable
- 1.11 Concepts and constrained
auto
types- 1.11.1 Constrained
auto
variables - 1.11.2 Constrained
auto
return-type
- 1.11.1 Constrained
- 1.12 The power of Concepts:
requires
instead ofenable_if
- 1.12.1 Call method based in requires
- 1.12.2 Conditional copy operations
- 1.12.3 Conditional destructor
- 1.12.4 Conditional methods
- 1.13 Concepts ordering
- 1.13.1 Subsumption rules details
- 1.13.2 One more thing, never say not
- 1.14 Improved error message
- 1.1 Programming before Concepts
- 2 Coroutines
- 2.1 Regular functions and their control flow
- 2.2 What are Coroutines
- 2.2.1 Generating a sequence with coroutines
- 2.3 The elements of Coroutines in C++
- 2.3.1 Stackless Coroutines in C++
- 2.3.2 The new kids on the block:
co_await
,co_return
andco_yield
- 2.3.3 The generator
- 2.3.4 The
promise_type
- 2.3.5 An iterator for
generator
- 2.3.6 Coroutine customization points
- 2.3.7 Coroutines restrictions
- 2.4 Writing a byte-stream parser the old way
- 2.5 A byte-stream parser with Coroutines
- 2.5.1 Writing the
Parse
function as coroutine - 2.5.2 Creating an Awaitable type
- 2.5.3 A more flexible
promise_type
- 2.5.4 Another generator the FSM
- 2.5.5 Simulating a network byte stream
- 2.5.6 Plugging the pieces together
- 2.5.1 Writing the
- 2.6 A different strategy of the
Parse
generator - 2.7 Using a coroutine with custom
new
/delete
- 2.8 Using a coroutine with a custom allocator
- 2.9 Exceptions in coroutines
- 3 Ranges: The next generation STL
- 3.1 Motivation
- 3.1.1 Avoid code duplication
- 3.1.2 Consistency
- 3.1.3 Safety
- 3.1.4 Composability
- 3.2 The who is who of ranges
- 3.3 A range
- 3.3.1 What is a
common_range
? - 3.3.2 A
sized_range
- 3.3.1 What is a
- 3.4 A range algorithm
- 3.4.1 Projections for range algorithms
- 3.5 A view into a range
- 3.6 A range adaptor
- 3.6.1 A custom range adaptor
- 3.7 The new ranges namespaces
- 3.8 Ranges Concepts
- 3.9 Views
- 3.10 Creating a custom range
- 3.10.1 Implementing the view
- 3.10.2 A range adaptor for
custom_take_view
- 3.10.3 Add the pipe-syntax to
custom_take_view
- 3.10.4 A more generalized pipe-syntax implementation
- 3.1 Motivation
- 4 Modules
- 4.1 Background about why modules
- 4.1.1 The include hell
- 4.1.2 I like to have secrets
- 4.2 Creating modules
- 4.2.1 A header unit
- 4.2.2 A named module
- 4.3 Applying modules to an existing code base
- 4.3.1 Down with namespace details
- 4.3.2 Now I can hide my secrets from you...
- 4.3.3 What you gain
- 4.3.4 Templates in modules
- 4.3.5 Down with
DEBUG
- 4.3.6 In-line definitions of class members
- 4.3.7 There are some limits
- 4.1 Background about why modules
- 5 std::format: Modern & type-safe text formatting
- 5.1 Formatting a string before C++20
- 5.1.1 Formatting a stock index with
iostreams
- 5.1.2 Formatting a stock index with
printf
- 5.1.1 Formatting a stock index with
- 5.2 Formatting a string using
std::format
- 5.2.1
std::format
specifiers - 5.2.2 Escaping
- 5.2.3 Localization
- 5.2.4 Formatting floating-point numbers
- 5.2.1
- 5.3 Formatting a custom type
- 5.3.1 Writing a custom formatter
- 5.3.2 Parsing a custom format specifier
- 5.4 Referring to a format argument
- 5.5 Using a custom buffer
- 5.5.1 Formatting into a dynamically sized buffer
- 5.5.2 Formatting into a fixed sized buffer
- 5.6 Writing our own logging function
- 5.6.1 Prefer
make_format_args
when forwarding an argument pack - 5.6.2 Create the format specifier at compile-time
- 5.6.3 Formatting the time
- 5.6.1 Prefer
- 5.1 Formatting a string before C++20
- 6 Three-way comparisons: Simplify your comparisons
- 6.1 Writing a class with equal comparison
- 6.1.1 Comparing different types
- 6.1.2 Less hand-written code with operator reverse, rewrite and
=default
- 6.2 Writing a class with ordering comparison, pre C++20
- 6.3 Writing a class with ordering comparison in C++20
- 6.3.1 Member-wise comparison with
=default
- 6.3.1 Member-wise comparison with
- 6.4 The different comparison categories
- 6.4.1 The comparison categories
- 6.4.2 The comparison strength:
strong
orweak
- 6.4.3 Another comparison strength: partial ordering
- 6.4.4 Named comparison functions
- 6.5 Converting between comparison categories
- 6.6 New operator abilities: reverse and rewrite
- 6.7 The power of the default spaceship
- 6.8 Applying a custom sort order
- 6.9 Spaceship-operation interaction with existing code
- 6.1 Writing a class with equal comparison
- 7 Lambdas in C++20: New features
- 7.1 [=, this] as a lambda capture
- 7.2 Default-constructible lambdas
- 7.3 Captureless lambdas in unevaluated contexts
- 7.4 Lambdas in generic code
- 7.4.1 Lambdas with templated-head
- 7.4.2 Variadic lambda arguments
- 7.4.3 Forwarding variadic lambda arguments
- 7.5 Pack expansions in lambda init-captures
- 7.6 Restricting lambdas with Concepts
- 8 Aggregate initialization
- 8.1 What is an aggregate
- 8.2 Designated initializers
- 8.2.1 Designated initializers in C
- 8.2.2 Designated initializers in C++20
- 8.2.3 Initializing a subset of an aggregate with designated initializers
- 8.2.4 Initialize a subset with designated initializers without in-class member initializers
- 8.2.5 Named arguments in C++: Aggregates with designated initializers
- 8.2.6 Overload resolution and designated initializers
- 8.3 Direct-initialization for aggregates
- 8.3.1 Initialization forms: Braced or parenthesis initialization
- 8.3.2 Aggregates with user-declared constructors
- 8.4 Class Template Argument Deduction for aggregates
- 9 Class-types as non-type template parameters
- 9.1 What are non-type template parameters again
- 9.2 The requirements for class types as non-type template parameters
- 9.3 Class types as non-type template parameters
- 9.3.1 A first contact with class types as NTTP
- 9.3.2 What compile-time data do we have
- 9.4 Building a format function with specifier count check
- 9.4.1 A first
print
function - 9.4.2 Optimizing the format string creation
- 9.4.3 Checking the number of specifiers in a format string
- 9.4.4 Checking if type and specifiers do match
- 9.4.5 Enable more use-cases and prevent mistakes
- 9.4.1 A first
- 10 New STL elements
- 10.1
bit_cast
: Reinterpreting your objects - 10.2
endian
: Endianess detection at compile time - 10.3
to_array
- 10.4
span
: A view of continuous memory - 10.5
source_location
: The modern way of__FUNCTION__
- 10.5.1 Writing a custom assert function
- 10.5.2 Writing a custom assert function with C++20
- 10.5.3 Writing a custom log function with C++20
- 10.6
contains
for all associative containers - 10.7
start_with
ends_with
forstd::string
- 10.1
- 11 Language Updates
- 11.1 Range-based for-loops with initializers
- 11.1.1 Using a counter-variable in a range-based for-loop
- 11.1.2 A workaround for temporaries
- 11.2 New Attributes
- 11.2.1
likely
/unlikely
- 11.2.2
no_unique_address
- 11.2.1
- 11.3 using enums
- 11.4 conditional
explicit
- 11.4.1 Writing a well behaving wrapper
- 11.4.2 Communicate your intention, explicitly
- 11.1 Range-based for-loops with initializers
- 12 Doing (more) things at compile-time
- 12.1 The two worlds: compile- vs. run-time
- 12.1.1 The benefit of compile-time execution
- 12.2
is_constant_evaluated
: Is this aconstexpr
-context?- 12.2.1 Different things at compile- and run-time
- 12.2.2
is_constant_evaluated
is a run-time value
- 12.3 Less restrictive
constexpr
-function requirements- 12.3.1
new
/delete
: Dynamic allocations during compile-time - 12.3.2 A
constexpr
std::vector
- 12.3.1
- 12.4 Utilizing the new compile-time world: Sketching a car racing game
- 12.5
consteval
: Do things guaranteed at compile-time- 12.5.1
as_constant
a use-case forconsteval
- 12.5.2 Force compile-time evaluation for compile-time checks
- 12.5.3
is_constant_evaluated
doesn't make it compile-time
- 12.5.1
- 12.6
constinit
: Initialize a non-const
object at compile-time- 12.6.1 The static initialization order problem
- 12.6.2 Ensure compile-time initialization
- 12.1 The two worlds: compile- vs. run-time
- Acronyms
- Bibliography
- Index
Andreas