Advent 2021: C++
This blog is part of the 24 posts long series "Advent 2021":
- Advent 2021: Intro (December 01, 2021)
- Advent 2021: C++ (December 02, 2021)
- Advent 2021: C# (December 03, 2021)
- Advent 2021: Python (December 04, 2021)
- Advent 2021: Go (December 05, 2021)
- Advent 2021: TypeScript (December 06, 2021)
- Advent 2021: CMake (December 07, 2021)
- Advent 2021: Django (December 08, 2021)
- Advent 2021: Angular (December 09, 2021)
- Advent 2021: Flask (December 10, 2021)
- Advent 2021: gRPC (December 11, 2021)
- Advent 2021: GraphQL (December 12, 2021)
- Advent 2021: XML & JSON (December 13, 2021)
- Advent 2021: Matplotlib, Pandas & Numpy (December 14, 2021)
- Advent 2021: Linux (December 15, 2021)
- Advent 2021: Ansible (December 16, 2021)
- Advent 2021: SQLite (December 17, 2021)
- Advent 2021: Catch2 (December 18, 2021)
- Advent 2021: Zstandard (December 19, 2021)
- Advent 2021: ZFS (December 20, 2021)
- Advent 2021: Thunderbird (December 21, 2021)
- Advent 2021: Visual Studio Code (December 22, 2021)
- Advent 2021: Blender (December 23, 2021)
- Advent 2021: Open source (December 24, 2021)
I’m kicking off this series with … programming languages! Starting with C++, the first “real” programming language I learned. Over the years, I not only ended up as a fairly competent C++ programmer, but also someone who really likes C++. I’ve been thinking quite a bit about what it actually is in C++ that I enjoy, and broadly speaking, there are three things:
- The core language itself
- How the language is evolving
- The ecosystem around it
Let’s get the last item out of the door quickly, because it’s the least exciting in my opinion. C++ has access to all C and C++ libraries, and I think it’s fair to say that C and C++ libraries form the bedrock of a large part of today’s programming world. Major operating systems have C interfaces, and many of the workhorse libraries and frameworks we use are written in C/C++. For me, that means that I can get access to a mature, robust, battle-tested ecosystem, which may not be that exciting due to the decades of development, but it does get the job done.
There’s one aspect of the ecosystem however that I cannot praise enough: cppreference.com When I started, the definite documentation for C++ used to be the ISO standard. Which is not only hard to read, but also difficult to search at best. Fortunately, cppreference is available these days and I can’t stress how big the impact of that website has been. Finally, there’s a one-stop shop for all things C++: Standard library, language features, as well as “non-core” topics like compiler support.
Now, onto the core language itself. I’d like to pick one feature here that I really like: The type system! It’s powerful, allows for little to no abstraction cost, and used correctly, it can produce very readable code. I’ve been looking for examples in my home framework and a great one I found is handling of angles, or more specifically, what unit is used. Is an angle in degree or radian? Who knows! But with the C++ type system, you can embed this information in the type system and stop worrying about it. Here’s a snippet how I’m using it:
Radian heading = GetHeading();
if (heading > Degree (360.f)) {
heading -= Degree (360.f);
}
Being able to put meaning into types and use them to naturally abstract things is something I always enjoy doing in C++. I think type safety is one of the strongest feature of this language and it saved me from many bugs over the years. It also took me many years to fully appreciate when and how to apply this, but these days, I feel like the type system is a good friend that helps me to get my job done.
The other bit I want to highlight is how the language is evolving. Back in the old days when I started, it seemed like C++ has stagnated. New releases took a long time, and compilers were lagging a lot. Fortunately, this has dramatically changed for the better: C++ is now on a 3-year cadence (C++11, 14, 17, 20 …) and delivering major improvements every time. Every time a new release comes out, I refactor my home framework to get a feeling where the language is heading. While it may seem sometimes as if C++ is making things more and more complex, I eventually do end up deleting code with every new release. For example, the introduction of concepts allowed me to remove SFINAE code which was difficult to understand and maintain. I don’t think anyone did enjoy writing things like:
typename std::enable_if<! std::is_pointer<T>::value>::type
SetArgument (const int index, const T& t)
With concepts, that kind of code turns into – in my opinion, much more readable – requires
constraint:
template <typename T>
requires (!std::is_pointer_v<T>)
void SetArgument (const int index, const T& t)
The spaceship operator allowed me to remove a bunch of boilerplate I was writing as well. Generally speaking, new C++ releases do add more tools, but they also allow to forget typical “code patterns” (like the aforementioned SFNIAE.) I think that’s a good development – it means learning less “arcane” knowledge and having more discoverable mechanisms. Looking at the most recent release – C++20 – and some exciting changes it brought like modules, I think the future for C++ is quite bright, and I’m personally looking forward to using things like modules and future iterations of C++.