C++ Annotated: April 2021
Please welcome the April edition of C++ Annotated and its companion, the No Diagnostic Required show!
As you might know, we deliver this digest in a few different forms. You can 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).
- P0323: std::expected
- P2128: multidimensional subscript operator
- P2321: zip
- P2358: defining contracts
- CLion 2021.1 release and 2021.2 roadmap
- ReSharper 2021.1 release and a brand-new Rider for Unreal Engine on macOS
- GCC 11 with C++ modules
- CUDA support in Visual Studio Code
- Pure Virtual C++
- C++ Foundation annual survey results
- And finally, what is possible in modern C++ that wasn’t in C++98
Watch the new episode of No Diagnostic Required below, or just keep reading this blog post for all the latest news!
As usual, we’ve picked a few proposals from this month’s committee mailing to highlight. As these are all at various stages of being discussed in the committee, there are no guarantees they will make it into a future standard, but some of them are definitely… expected!
This proposal is now on R10 – the first version was back in 2016 – and it’s not even the first time we’ve discussed it here. But R9 was back in 2019, so what’s changed since then?
In terms of design, and even wording, not much. The primary change is that, whereas R9 was based on the Library Fundamentals TS, the direction from LEWG (the Library Evolution Working Group) is that it should target the IS (the main standard) instead. There was quite a strong consensus, which shows that this is considered an important vocabulary type. Hopefully this is reassuring to those that were disheartened when
std::expected didn’t make it into C++20. That was just because it didn’t get through wording in time, rather than being voted against – so it should, hopefully, have a smooth run into C++23.
But what is
std::expected? It’s a choice type, along the lines of
std::variant, but specialized for return types and error handling. In the “expected’ (happy path) case, a value of a normal return type is held. But if an error prevents that type from being returned, then a value of the error type can be supplied, instead. Ergonomically it works much like
std::optional, but with the ability to carry the error value in the “unexpected” case. For a bit more about it, including those potential monadic operations – as well as some of the other proposals relating to error handling in C++ – see my talk, Dawn of a New Error.
Something else that’s expected, but perhaps sooner than expected, is this proposal for extending the subscript operator,
, with multiple arguments. Why expected? Because, to lay the groundwork for this, we deprecated use of the comma operator within the subscript operator in C++20. Why sooner than expected? Because this proposal includes removing comma operator support. That’s a very rapid turnaround! For comparison,
auto_ptr was deprecated in C++11 (although, spiritually, it was deprecated in the community long before that), then removed in C++17 – and that was seen as quite fast! However, while
auto_ptr was widely used in older code, being a fundamental vocabulary type in C++98, use of the comma operator within the subscript operator is quite rare.
But why do we need this ability? Right now, libraries that define types for things like multidimensional arrays, matrices, grids, etc. (including types in the standard library, like
mdarray), tend to resort to overloading the call operator instead. While this works – indeed the usage would be exactly the same – it’s a compromise. As the paper claims, it doesn’t convey the intention as clearly.
Continuing the trend of proposing library features that augment C++20 features which we didn’t have the time, or the scope, to get into C++20 itself: this month we have zip. Actually R0 came in February, but we didn’t discuss it then, and now R1 is here, anyway.
Zipping is a facility found in many languages that deal with range-like features. It allows you to combine two or more ranges into a single range view where each element is a tuple – with one item from each of the original ranges.
A common example is when you want to iterate, say, a vector, but you also want to have access to the index into the vector. Of course you could do that by using a classic, C-style, for loop – and index into the vector within the body. But that gives up many of the benefits of range-based for loops, and it may not be possible at all if you’re using algorithms. However, if you can generate a view of an increasing counter, say with
std::ranges::views::iota, you can iterate the zip of that and the vector itself and get both the value and the element on each iteration. In practice there are some issues with using
iota in this way, in the general case, so a more specialized facility,
std::ranges::views::enumerate, is proposed as P2164 (which also makes it more convenient).
The design discussion around
zip itself and its sibling facilities (
adjacent_transform) – as well as
enumerate – are covered by reference to an earlier paper, P2214: A Plan for C++23 Ranges.
This is another paper that distills some of the ongoing discussion in SG21 – the contracts study group. Last time we mentioned that one of the problems with the original discussion of contracts – leading up to their removal from C++20 – was a lack of common ground between parties with different interests. SG21 has discovered the hard way that there has been a lack of agreement on the definitions of terms being used to describe use cases. So this paper is an attempt to bring some much-needed clarity by setting out specific definitions on many of the terms commonly used in contracts discussion. The paper even starts out, after an appropriate quote from Humpty Dumpty, by saying, “This paper defines terms so that the SG21 group doesn’t talk past each other”! It’s a short but information-dense paper that’s well worth a read if you want to see how deep the rabbit hole goes.
CLion 2021.1 release and the 2021.2 roadmap
CLion 2021.1 was released in the first week of April. The main focus of this first major update in 2021 is code analysis, enhancements for support project models, and feature parity in remote development and in the debugger. If you asked me to name the top 3 benefits of this release, I would say:
- Postfix completion for C and C++. With it, you can pass the expression you’ve just typed to a free function as the first argument. You will especially like it if you miss Uniform Function Call Syntax (UFCS) in C and C++.
- Global data flow analysis. It will capture things like dangling pointers and null pointers dereferencing for you within whole translation units, not just within function bodies as it did before.
- Branch coverage (in addition to the existing statement coverage) and dynamic analysis are now available in remote mode.
Also worth mentioning are new MISRA checks for embedded developers, Clazy for Qt projects, remote Makefile projects, and Code With Me, a new JetBrains service for collaborative development and pair programming.
If you are interested to know what’s coming next to CLion, the preliminary roadmap for 2021.2 is now available. It includes, among other things, Lifetime analysis, custom compiler support, initial work on CMake presets, more goodies for embedded developers, and much more.
ReSharper 2021.1 release and Rider for Unreal Engine on macOS
Version 2021.1 of ReSharper C++, our extension for Visual Studio for C++ developers, was also released in April. The biggest change is Syntax Style settings with accompanying inspections, quick-fixes, and context actions – we talked about them in March already. This update also delivered the following enhancements:
- Many new C++20 additions, like class types in non-type template parameters, new CTAD rules, and coroutine-related syntax in regular and postfix code completion.
- Initial support for Unreal Engine 5 and other UE-specific additions for those who create games in Visual Studio with ReSharper C++.
- New code analysis checks that keep the code simpler by finding things like redundant template arguments or redundant cast expressions.
Speaking of game development with Unreal Engine, JetBrains Rider for Unreal Engine, which is in preview for now, has announced a macOS version. Mac users can now get the same smart UE support that Windows users of JetBrains Rider or ReSharper C++ have been benefiting from for the past year.
Wondering how major compilers are doing these days? GCC and Clang both have major updates! GCC 11 is finally delivering C++20 modules support, still with some incompleteness, and it requires the
-fmodules-ts compilation flag to be passed. There are more C++20 additions in this release and even some additional C++23 draft features, along with C++20/C++23 changes to the
libstdc++ library. Additionally, the new version defaults to
-std=gnu++17 instead of
-std=gnu++14. This might cause some porting issues, so do make sure you’ve read the Porting to GCC 11 article if you are on GCC.
CUDA support in Visual Studio Code
Microsoft and NVIDIA have partnered together to work on better CUDA support in Visual Studio Code. This was announced in both NVIDIA and Microsoft blog posts.
IntelliSense for CUDA kernel functions is available now in VS Code Insiders (preview) builds. But it’s also part of a bigger effort, NVIDIA Nsight Visual Studio Code Edition. The latter additionally promises build and debug support for GPU kernels, including:
- Standard breakpoints and stepping abilities for CPU and GPU code.
- Conditional breakpoints with expression evaluation.
- Call-stack, register, and variable views.
Builds are not yet publicly available, but you can fill out a form on the NVIDIA site to show them you’re interested in the preview.
Pure Virtual C++
Microsoft announced a free one-day virtual conference for the C++ community. It will run on May 3 and will include pre-recorded sessions with a live Q&A with each speaker. The program targets the most recent additions to Microsoft tooling and shows Microsoft particular interest in several important community topics:
- Two talks on C++ Modules, explaining visibility and reachability concepts, and giving an overall recap of where we are now with the real usage for C++ Modules in practice.
- A collaborative talk with Kitware on their brand-new CMake presets feature.
- As the biggest pain-point in C++ is managing dependencies, an update on vcpkg will be presented.
- Static and runtime analysis (AddressSanitizer) tooling for better C++ code quality.
C++Now Online 2021 will be running May 2 – May 7, and the program is already available on the conference website, with keynote sessions from:
- Bill Hoffman, founder of Kitware, the company behind CMake. No surprise, Bill will be talking about this build system (the talk is called CMake: One Tool To Build Them All), the most popular project model in the C++ ecosystem right now. The keynote session will cover the history behind it and its most important modern features, and hopefully will give a first-hand account of the main philosophy behind the technology.
- Bryce Adelstein Lelbach, NVIDIA’s HPC Programming Models Architect and chair of the Standard C++ Library Evolution working group. In his talk, Bryce will share the principles that are shaping the evolution of the C++ Standard Library. Hopefully he will answer the question that’s bothering many C++ developers who are following the evolution of the language: what should go into the STL and what should not?
- Tony Van Eerd, undoubtedly the best presenter in the C++ community (and beyond) and author of the famous Tony Tables approach, which uses examples to explain how changes to the language transform the code. Tony’s keynote is dedicated to SOLID Principles, which are celebrating their 20th birthday! If you are still not aware of what the acronym stands for, this talk will give you an answer and will also discuss how it fits into modern C++.
C++ Foundation annual survey results
The Standard C++ Foundation has published the results of their annual survey for 2021. The goal of the research is to understand the C++ community better by collecting information about the areas of development, experience, preferences for language standards and tools, main pain-points, and C++-related habits.
It’s no surprise that one of the major causes of frustration for developers is managing libraries their application depends on. Package and dependency managers are still far from being standard tooling in C++ – despite such strong players as Conan and vcpkg. That’s why “The library source code is part of my build” is a true statement for nearly 69% of respondents, while Conan and vcpkg get about 16% and 15% respectively. CMake is a build system of choice for nearly 80% of respondents, and at the same time managing CMake projects is super-problematic for a bit less than 32%.
And of course, the most frequently asked question is about the C++ standard. Just 40% of respondents are allowed to use C++20, whereas four out of five can use C++17. But the most promising result is that in the next 12 months:
- 46% plan to allow the usage of Concepts in their products
- 36% plan to allow Coroutines
- 38% plan to allow Modules
Interestingly, most of the collected responses came from developers with 10+ years of experience in C++, which means the audience is very experienced and probably highly skilled. We usually keep this in mind when comparing the results of our Developer Ecosystem research against the C++ Foundation survey results. In our survey the C++ audience has slightly less experience in C++ (1-5 years for the majority of the audience). By the way, the results of the JetBrains Developer Ecosystem survey for 2021 should be going live in June, so stay tuned!
And finally, what is possible in modern C++ that wasn’t in C++98
This Reddit thread re-ignited an age-old argument: isn’t any programming language, no matter how advanced, just syntactic sugar over earlier versions of the same language, possibly all the way back to assembler? There’s some truth to that, but one interesting point emerged from the discussion: a systems language is a point of interface between application code and the operating system it runs on (assuming an OS). In some cases, the way the language is defined makes it impossible to do certain things without language support. The example that comes up a lot in the thread is of the C++ memory model, which was very under-defined prior to C++11 – especially with regard to threading. That threading libraries existed, and appeared to work, was not guaranteed by the standard at all – and writing reliable threading code portably was fraught!
Another interesting point raised was that move semantics allow you to write generic code that wouldn’t have been possible before, because there was no way to distinguish between an lvalue and an rvalue.
Of course many of the changes that have come in C++11, and beyond, while technically syntactic sugar over facilities we had before, were so dramatic in the level of convenience they brought that they were often impractical before, even if not impossible. Lambdas are a good example. Variadic templates must rank up there quite highly for anyone who had to do them the long way round before C++11!