Modern C++

Introducing the C++ Core Guidelines

Whether you're new to C++ or a seasoned C++ coder, there are times when deciding how to do something seems arbitrary. The C++ Core Guidelines have been written to guide developers of all experience levels through some of the choices we make to help us write code that is fast, readable, maintainable, and sensible.

I've been writing C++ since before Microsoft had a C++ compiler. It's been well more than 20 years, perhaps closer to 30. And in all that time, I've learned a lot of C++ and a lot about how to write good software. I've also learned about the parts of C++ I don't really want to use -- and, interestingly, just what those parts are has really changed over time!

C++ has a reputation as "the language for smart people" -- and that's not always a compliment. Plenty of people find it just too difficult and, frankly, scary. They worry about buffer overflows, memory leaks, memory corruption, insane bugs from tiny typos and the like. They don't know how anyone remembers the correct syntax for declaring a function pointer. (Spoiler alert: Basically nobody does; we copy it from some other place we did it before, or the Internet. Two or three people can show off their inside-out writing skills, but it's more a party trick than anything else.)

When newcomers to the language express these feelings, often we old-timers tell them off for it. We claim that some opaque construct is vital for performance. We encourage them to believe (often incorrectly) that writing C++ is a constant trade-off between readability and performance, between safety and performance, between maintainability and performance -- and we imply that performance should always win. The truth is that C++ has changed a lot during this century, and compilers and optimizers have changed, too. There's a good chance that when you have a choice to make in how to do things, the readable and safe way to do it is either just as fast as the hard way, or even faster.

A growing number of C++ developers want to get the message out about this variant of C++. By choosing not to use certain features, they work with a safer subset of the language. Their applications are easier to write, easier to read and test, and easier to maintain. They have fewer bugs and are less likely to encounter runtime errors. Yet these applications, safe by construction, safe by default, are as fast or faster as they would be if they'd been written in the style that was popular last century. They have written a description of this variant in the form of a large document with hundreds of guidelines for writing safe, readable, truly modern C++ that does not accept a performance reduction in exchange for its sanity. To quote the README file for the project:

Following the rules will lead to code that is statically type safe, has no resource leaks, and catches many more programming logic errors than is common in code today. And it will run fast -- you can afford to do things right.

These guidelines are online and the GitHub site. You can download a copy, but I prefer to use the live version, because it's always up-to-date. You can explore some of the other areas in the repo -- learn who's working on it (the inventor of the language and the head of the ISO C++ Standards Committee, for two, and they have some illustrious company). They're written as a series of, well, guidelines, telling you not to use certain patterns, to prefer one approach to another and so on. Almost all of them have an explanation and a code sample, though some are still incomplete. They're organized into sections: Functions, Resource Management, Concurrency, and so on, and there are plenty of links back and forth within the document and to other resources.

Many of the guidelines are not machine-checkable -- how could a compiler or other tool verify that you've expressed your intent in code (by choosing appropriate type names and using functions) rather than relying on comments?

But some are. After the main body of the guidelines comes a small set of profiles, designed to achieve specific goals (type safety, bounds safety and lifetime safety) and to be checkable by tools such as a compiler or a standalone checker. Such checkers are beginning to be created -- Visual Studio users will be interested in the NuGet package called CppCoreChecker that changes the behavior of the static analysis tool to check against the bounds and type safety profiles, and the experimental package called ExperimentalCppCoreCheck that does the same for the lifetime safety profile.

I'll be covering these in more detail in later columns.

I love the guidelines for their ability to teach all of us how to write better C++. Some of them are simple enough that once you read them, you just start writing code that way and that's all. But some of them provide a great opportunity to explain parts of the language or the Standard Library that are relatively new, or that not all developers know. So by getting a good understanding of a particular guideline, you'll also learn more about C++ and how to write it well.

Please join me on a trip through selected guidelines (and the related parts of the language and library) so that you, too, can know how to write code that is easier, safe, and faster than what you might have written off the top of your head.