Monday 1 July 2024

Learn C++ by Example: Chapter 8

I have been sharing some details about my latest book "Learn C++ by Example", and gave an overview of chapter 7 last time. There are 9 chapters, so this is the penultimate blog about the book contents.




You can buy my book directly here: http://mng.bz/AdAQ - or just go look at the table of contents. You can also buy it from Amazon: https://amzn.to/4dMJ0aG

Chapter 8 is predominantly about unordered maps and coroutines. The previous chapter used std::map, which has been in C++ for a long time but allowed us to learn several new features anyway. This chapter uses an std::unordered_map for contrast. The unordered containers were introduced in C++11. They use hashes to place elements in buckets, so the std::unordered_map is a hash map. There are many overloads of std::hash but you might need to write one to use the hash map, for example for your own class or std::tuple.

The mini-project in this chapter is a game of matching pennies. Two players secretly pick heads or tails on a coin, and simultaneously show their choice. One player is trying to get a match, and the other tries to avoid this. It's not hard to write code where the computer wins on a match, using random numbers for the computer's turn, giving a basic version of the game. 

Now, Claude E. Shannon wrote a short paper in 1953 called “A Mind-Reading (?) Machine” Yes, that Claude Elwood Shannon - the accomplished unicyclist and founder of information theory. The paper has a question mark in the title because the machine isn't really mind-reading. Shannon tracked whether the penultimate outcome was a win or lose, and if the player then changed from heads to tails (or vice versa) or played the same move and thereby won or lost. The three elements can form a lookup table and we can record whether the next choice was a change or not. If we just store the last two values  (change or not) for a given state, we can perform a lookup and if they match, make a prediction. If they don't match, the computer plays at random. The mind-reading machine is surprisingly effective, though you can outsmart it if you track the same state yourself. 

Coding it up gives the opportunity to practice all kinds of C++ features, as well as think about how to form a hash for the three part key. The first part of the chapter creates a MindReader class template, taking a generator and distribution as template parameters, making the code using randomness easy to test. Armed with a mind reader, we then see how to use this in a coroutine. Doing so makes no difference to the matching pennies game, but is an opportunity to learn about this new, much discussed feature of C++.  

You can pause a coroutine, say after yielding a result, and resume later. CppReference says 
This allows for sequential code that executes asynchronously (e.g. to handle non-blocking I/O without explicit callbacks), and also supports algorithms on lazy-computed infinite sequences and other uses.
Coroutines allow cooperative multitasking for example running some code, then suspending while awaiting a result. You need to write a lot of boilerplate to get a coroutine working, but the compiler will help you remember what to add. Again, the compiler will point out anything you need if you forget something. 

If you see a function with one of the following 
  • co_await
  • co_yield
  • co_return
the function is a coroutine. The return type must then fill in the boilerplate, including how to start and stop, and what to do with a co_await, co_yield or co_return

Ivan Cukic gave a keynote at MeetingCpp in 2023. He mentioned coroutines (and lots of other ways to style C++ code for various use cases and neatness). Go look at the slides: From slide 69, he talks about "C++ error handling, let’s abuse the co_await operator." An usual use of coroutines, but interesting.

So, some questions for you:
  1. Why are the C++11 containers called unordered?
  2. How would you write a hash function for a std::tuple, say of just three elements?
  3. Can you list all the parts a coroutine's return type needs?

No comments:

Post a Comment