Daily bit(e) of C++ | Learn Modern C++ 1/N
Daily bit(e) of C++ #83 , A Modern-only C++ course (including C++23), part 1 of N
Welcome to a new sub-series that will take over the Saturday slot.
In this series, I will carefully guide you through the C++ language to bring you up to a point where you can comfortably start working on application-level C++ development. To achieve that, the course will be example heavy and contain homework.
In this article, I will review the course's prerequisites and aim. Then, I will discuss the setup and how to use this course effectively.
Prerequisites
This course assumes that you can write simple code. The programming language doesn’t matter, but I expect you to understand concepts like variables, conditions, loops, etc.
You will need Docker (Desktop), and Visual Studio Code installed on your machine to work on homework.
Due to the components used in the course software stack, you will need a 64-bit system, but the stack should work fine on both the x86-64 and arm64 systems (let me know if you run into issues).
The aim
My daily bit(e) series already covers the C++ language; however, where the main series approaches the teaching by examining small pieces of the language under a microscope, this course is aimed to be a guided tour through the vast lands of C++.
Notably, we will explore Modern C++; therefore, do not expect a visit to the swamps of C, no matter how cool the ambience might be.
The main goal is to get you set up with the knowledge that will allow you to work on application-level projects (I will eventually make another course that will level you up to library-level development).
Consequently, this course is not attempting to be complete in any sense. Instead, it will be shallow and focused, covering only the essential parts of the language.
The setup
Each lesson will rely heavily on Compiler Explorer, with each code example linking to a corresponding Compiler Explorer setup, where you can play with the code.
For example:
The examples in the text will sometimes skip over boilerplate code for brevity, but the Compiler Explorer setup will always be complete.
Using Compiler Explorer is reasonably straightforward. As you edit the code in the code editor window, the program will be periodically rebuilt and executed. You will see the compilation output (errors, warnings) and execution output in the output window.
We will also take advantage of configuring run arguments and input in some of the examples.
VSCode
While Compiler Explorer is great for fiddling with small examples, we need something more robust for homework, so I have prepared a VSCode-based setup.
Each lesson will come with a homework repository. This will contain the scaffolding code and pre-written tests. For this example, we will be using https://github.com/HappyCerberus/daily-bite-course-01.
Alternatively, each repository is also set to be a template. If you want your copy, go to the repository and select “Use this template” (the button might be hidden on narrow views). From then on, use your URL.
Open VSCode and press Ctrl+Shift+P / Shift+Command+P (or View>Command Palette)
Write “Clone”, and select “Git: Clone”
Paste in the URL (https://github.com/HappyCerberus/daily-bite-course-01) and press Enter.
You will be prompted to select a location (which doesn’t matter), and after the repository is cloned, you should get a prompt to reopen the repository in a DevContainer:
Confirm the prompt, and the repository will be reopened in a custom Docker image with GCC 12.2. The green button in the bottom left should now show “Dev Container”.
If you closed the prompt or need to do this manually, click the green button and select “Reopen in Container”. Once inside the container, you can browse the code and open the terminal (View>Terminal).
The goal for each lesson will typically be to make all tests pass, but first, let’s run the hello world program “helloworld/main.cc”. For that, we can use the “bazel run” command:
The first run may be slow since Bazelisk (a tool to install Bazel) will need to download the correct version of Bazel, and then Bazel will need to fetch all required dependencies.
Now that the basics work, you can try to achieve the goal, which is to have all the tests pass:
bazel test //...
bazel test --config=ubsan //...
bazel test --config=addrsan //...
One tip I have for you is that the VSCode terminal supports hyperlinks, and hovering over file names and, notably, line numbers when you see an error will allow you to jump straight to the relevant piece of code.
Debugging
We will cover debugging as one of the lessons in the course, but if you are already familiar and want to use it during the course, this section is for you.
The one part of VSCode that is a bit cumbersome comes from its very generic nature. VSCode doesn’t understand any particular language, and all functionality needs to be provided through plugins or manually configured.
The editor window will allow you to set breakpoints; however, you must provide a configuration of what exactly VSCode should do when you request a debug session.
I have prepared a configuration for an example test in “.vscode/launch.json”. You should be able to re-use this configuration changing the path to the binary as desired.
To start the debugging session:
compile with debug symbols using “
bazel build --config=debug //debugging:example_test
”set a breakpoint in the “
debugging/example_test.cc
“ file by clicking next to the line numbersstart a debugging session: Run>Start Debugging
How to use this course
Finally, I want to make a few recommendations on how to use this course most effectively.
If you are coming in with prior knowledge (or C knowledge), the most important thing is to stick with the tools presented in the course. You might already know multiple ways to achieve a particular goal, but sticking with the course material will allow you to re-learn the Modern C++ approach.
Play with the examples. The reason why each code example links to Compiler Explorer is so that you can experiment. Test your understanding by predicting what will happen if you adjust the code and then verify.
Try your best with the homework and only then look at the solutions. While I will provide example solutions to the homework, always try to solve it yourself first and only then look at the solution. If you failed to solve the problem, try re-implementing the example solution, as it will help to reinforce muscle memory.
Please let me know if something doesn’t work or if you are stuck. One of the things I’m trying to get out of posting this course online is to get a sense of how good the pacing is and to iron out any kinks. I will try my darndest to keep pace with the comments (as long as they are on-topic).
How can you help
Large series like this one take a lot of work to prepare. Please share if you know someone who could benefit from going through the course.
If you are new to Bazel and it was not clear how to run the test cases, it is `bazel test //functions:functions_test`. More details here https://bazel.build/start/cpp#introduction
Curious why did you pick Bazel build here?