C++ Annotated: May 2021
Please welcome the May edition of C++ Annotated and its companion, the No Diagnostic Required show!
If you are already subscribed, feel free to skip to the news. If you are new, though, you are welcome to explore all the formats we offer. Choose to read, listen, or watch our essential digest of this month’s C++ news:
- Read the digest published monthly on our blog (use the form on the right to subscribe to the whole blog).
- Subscribe to C++ Annotated emails by filling out this form.
- Watch the No Diagnostic Required show on YouTube. To be notified of new episodes, follow us on Twitter.
- Listen to our podcast – just search for “No Diagnostic Required” in your favorite podcast player (see the list of supported players).
Watch the May episode of No Diagnostic Required below, or just keep reading this blog post for all the latest news!
- Language news
- Conference news
Monadic operations for std::optional – P0798
Other languages with optional types tend to also have ways to compose code using them in well-defined ways. These ways are often known as the Monadic Operations, but you don’t have to understand monads to benefit from them. I won’t repeat the code samples, as we talked about this last month in the context of std::expected, but this month has seen some activity on the original std::optional version, too. To summarize, the result is that a significant amount of boiler plate code and indentation is eliminated and the flow of data through the code is much clearer.
The changes in this revision are fairly minor, with wording tweaks, adding constraints, and some little tidy-ups for consistency. This is reassuring, as it seems the design is in good shape and we’re getting ready to poll it for inclusion into the working draft. We’re hopeful, as this is an important component of an overall alternative error-handling strategy that is emerging for C++.
[[nodiscard]] in the Standard Library: Clause 23 Iterators library – P2377
Continuing that error-handling theme, although by no means limited to error-handling, [[nodiscard]] was introduced in C++17 as a way to inform both the user and compiler that a return value is an important or essential part of a function call and that ignoring it is probably a mistake. Compilers are not required to issue a warning, but are encouraged to do so. While this seems like a great idea – and would even have been better as a default, as the paper mentions – it hasn’t been applied extensively to the standard library itself. Doing so requires going through the library on a case by case basis to see what makes sense and what can be done without breaking valid code. This proposal is doing just that for the iterators library (so not really about error handling per se).
There was a late request to do so as part of C++20, but there were some cases, particularly around CPOs (Customization Point Objects), that weren’t clear cut and had to be postponed until later. Later has now come, and there is a section in the paper dedicated to CPOs with a few options, including one that results in “No Diagnostic Required”!
Pattern Matching with Exception handling – P2381
[[nodiscard]] has relevance to error handling when errors are propagated via return values (error codes, optionals, variants or the proposed std::expected). Error codes can be handled via switch statements, but for the more complex “sum types”, the handling quickly gets much more verbose (hence the monadic operations proposed for std::optional). Another way to cut through this is to use pattern matching in languages that support it. C++ may become such a language, as the pattern matching proposal continues to evolve. But in the context of error handling, if errors are propagated via exceptions, the syntax looks different, even if there are structural similarities. This paper proposes to lean into that and allow exceptions to be handled directly as part of the pattern matching syntax. That way, whether you use exceptions, error codes, or std::optional/ std::expected, the handling will look much the same.
This is definitely an interesting proposal, and I have some sympathy for the idea. I doubt it will be without controversy as it gets discussed. We’ll see where it goes.
Speaking of interesting, yet controversial, proposals to keep an eye on – let’s turn the dial up to 11! ABI compatibility – in the sense of whether code built with one version of the standard (especially the standard library) can link against the next – has been a hot topic for a couple of years, but seems to be heating up again. The discussion has moved on from whether an ABI break should occur at all to whether we can introduce ways to manage it. This proposal does seem like a promising take, but is also quite ambitious in a space that gets a lot of attention! It deals purely with library versioning (in both the standard library and user code) and works best when changes are purely incremental, though it can handle bigger breaks.
The way it works is that you first declare interface tags for the versions you support. These declarations may define superset/subset relations – similar to an inheritance hierarchy – so v2 may include all of v1, for example.
Then you use these tags to scope blocks (of state or functionality) that are specific to a version. Calling code can specify a version to resolve against, or just allow the latest version at compilation time to be used. It can also specify a minimum version in which case a dynamic binding wrapper is generated behind the scenes. That dynamic binding layer adds some overhead, but you only pay for that if and when you need it. Otherwise things are resolved statically (or as static as your interface) and the versions are baked into the object files.
So, the first impression: a promising approach which seems to have considered most concerns. But as it’s quite a significant set of features, with the potential for many unforeseen interactions, I’m sure this is going to get plenty of scrutiny and probably evolution before being accepted, if at all. If we don’t end up getting this, the discussion may inform another approach we can explore, so it’s great that we’re actively trying to break this deadlock with serious proposals.
Building LLVM with Llama
Llama is a tool for running UNIX commands inside of Amazon Lambda. And llamacc is a replacement for gcc and clang to execute the compilation in the cloud. If you use llamacc or llamac++ as your compiler, you can build using make or a similar build system with a much higher -j concurrency than your normal number of cores.
If you use Llama for a full build of clang+LLVM, the build will take about 80 seconds, as explained in this great article. It explains how the compilation process is executed in Amazon Lambda, as well as what could be done to optimize the build speed further. Interestingly, the LLVM build time seems to be affected by the issue in cmake’s Ninja generator, which emits unnecessary dependencies of add_custom_command(). The author also suggests that some really long files in LLVM can be split into several files to benefit from the parallel build. Could building in the cloud win over local builds on powerful machines in the future? Check out the article to decide.
A default value to dereference null pointers
Another short but practical post from Jonathan Boccara in his blog is dedicated to dealing with pointers in the same expressive way as with C++17 std::optional. As you may know, optional provides the value_or member function, which helps us handle optional’s nullity in a nice way. Could we have the same for pointers? Of course, but a free function rather than a member function. The blog post suggests an implementation and talks about inferring the return type of such a function. In the comments, readers discuss how they handle null pointers in their code. What would you add?
Finding bugs with AddressSanitizer
Exploring how tools can be applied to real-world open-source projects is always interesting and inspires broader usage. Microsoft has recently added AddressSanitizer to Visual Studio and published a blog post covering a few cases from the open source world where AddressSanitizer helped catch real-world bugs. In fact, they already caught an issue in the MSVC compiler and wrote about it earlier in April.
In this new blog post they cover three open-source projects:
- Boost: the problem was in dereferencing the end iterator.
- Azure IoT C SDK: the global buffer overflow happened there due to the incorrect size value passed to memcpy function.
- OpenSSL: another memory access bug, now caused by the assumption about the type sizes, which depends on the architecture the program is being compiled for and so might be incorrect.
The team also provides the links to the fixes in the GitHub repositories of the corresponding projects. Read the blog post for more details.
All major Vcpkg enterprise features are no longer experimental
Vcpkg, a C/C++ dependency manager from Microsoft, has made a huge step forward and announced that all core features are no longer experimental. The announcement relates to versioning and registries, combined with manifests and binary caching, which were announced earlier.
In short, these four major features are essential for package management:
- Versioning: allows users to rely on specific versions of the libraries.
- Registries: allows users to work with their own (even private) libraries via vcpkg.
- Manifests: enables the shareable way of maintaining the dependencies automatically (for MSBuild and CMake).
- Binary caching: allows reusing the pre-built binary libraries via vcpkg.
These features are not new, so what exactly has changed? It seems that a move from an experiment to a regular feature should guarantee some stability and quality of implementation. As the author of the blog post says, “we are confident enough to recommend using them in production environments.”
Along with the announcement, vcpkg started a new site with the updated branding. Its most interesting feature is the ability to browse the available packages. It searches as you type, showing you the list of matching packages, their versions, platform compatibility, and the vcpkg commands to install them.
CLion starts its 2021.2 Early Access Program
The CLion 2021.2 EAP program has begun! The first build introduces some noteworthy CMake enhancements, like initial support for CMake Presets. CLion can now load the build presets into its own CMake Profiles and use them for CMake generation on projects. The current mode only assumes read-only access in the CLion UI, even though users still can edit the JSON files with presets in the CLion editor and call the Load CMake Presets action again. The CLion team plans to collect the feedback and evolve the experience further after carefully listening to users’ needs and use cases. The first EAP build also bundles CMake v3.20 and brings templates for new CMake projects created in CLion.
To help users address safety issues in their C++ code, CLion 2021.1 EAP implements some of the Lifetime Analysis checks suggested in Herb Sutter’s proposal. The new version also adds support for interactive C++ interpreter, Cling, so you can now start a Cling session right in the IDE and easily send includes directives, lines of code, and whole selections to Cling. Check out other enhancements in the blog post and download the free EAP build to give it a try on your projects.
Early Access to C++Now 2021 recordings
Generally regarded as the year’s most academic event in the C++ community, C++Now moved to an online format in 2021 without losing any of its most distinctive qualities. It offered insightful discussions about some of today’s hottest topics, like C++ ABI stability, CMake, C++20 modules and concepts, and more. Together with Bloomberg, JetBrains is proud to support the event as a video sponsor and will bring you early access to this year’s conference recordings!
We will be publishing the talks over the course of several weeks on this page: http://jb.gg/cppnow. After all of the presentations are released, they will be made publicly available on C++Now’s official YouTube channel. But you don’t need to wait for that – you can start watching those that are already live on our web page. Stay tuned for more in the next few weeks!
Meeting C++’s call for papers has started
Meeting C++ 2021 has been announced as a fully online event, happening November 10–12, 2021. As more conference organizers are experimenting with online formats, Jen Wellers, who is hosting the Meeting C++ event, is planning to skip the keynotes this time and think more about other formats for the attendees. It will be interesting to see what he comes up with. Meanwhile, the call for papers is open until June 30.
Full schedule for C++ on Sea is announced
Another online format experiment will run quite soon, in the end of June and beginning of July. C++ on Sea has announced its full schedule. It consists of five tracks of workshops over two days, including half-day, one-day, and two-day workshops, as well as one more “classic” day of regular 60-minute talks. To give you a brief overview, the workshops include concurrency topics by Anthony Williams, a C++20 overview by Nicolai Josuttis, testing legacy code by Clare Macrae, and other interesting topics. I’ll also be giving a half-day workshop dedicated to Code Analysis in modern C++. The days of talks features Victor Ciura, Kevlin Henney, Mateusz Pusz, as well as closing keynotes by Ansel Sermersheim and Barbara Geller.