News

C++ Annotated June-August 2022: C++23 and C23 News, Language Tips and Tricks, and New Tools Releases

We’ve returned with all of the news from June, July, and August 2022 in our latest C++ Annotated digest. We’ve kept silent for a while, and despite these three months being less busy than the rest of the year for many, they were still jam-packed full of awesome news. So, expect today’s digest to be a bit longer than usual.

C++23 is in feature-freeze

In July’s virtual plenary session, C++23 reached its feature freeze! Timur Doumler wrote a meeting report on our blog covering the major changes that were agreed to at the meeting.

To address the coroutines use case, library support has been added with std::generator, so you no longer need to write it by hand. For better output printing, a new std::print that integrates with C++20 std::format is added. You can also find optional extended new floating-point types with a defined storage width and properties, defined according to ISO/IEC/IEEE 60559, and many improvements to ranges. Check out Timur’s post for the direct links to the proposals to learn the details.

C23 is huge

C also has some exciting big news – C23 is now in its final form! This blog post gives you a decent overview of many new changes linking to the related proposals.

C++ developers might not treat this as “big changes” but more like “obvious must-haves”. However, for C developers the update is huge:

  • Constexpr is now available for C objects, with compilers that guarantee this object is a constant expression.
  • While in C++ compound literals are challenging, in C they are now possible and supported in C23.
  • The new directive #embed has been added to help you include binaries in your code.
  • Requirements for variadic parameter lists have been relaxed. No first parameter, no va_start – pure -based function calls are now possible in C.
  • Improvements for enumerations now allow values greater than INT_MAX and smaller than INT_MIN.
  • The nullptr constant has been introduced.

The tragedy of C++ and the Carbon language from C++North

In July, the first edition of C++North took place in Toronto. The conference grew out of the Toronto C++ User Group. So even though there were just 180 attendees on site, many notable speakers were present. Timur Doumler wrote a trip report sharing his impression about the event.

We would like to highlight two keynotes here:

  • A talk by Chandler Carruth about the Carbon language, an “experimental successor language to C++”, which Google and a team of collaborators have been secretly working on for several years now. The language creators at Google were trying to reach many interesting goals like performance matching C++, interoperability with C++, low-level access to bits and addresses, easy to learn, and easy to migrate to. Check out the talk and the language details on GitHub. Do you think Carbon is something that could be coming next for C++?
  • A talk by Sean Parent about the evolution of C++. The key tragedy highlighted by Sean is that C++ being successful is also damaging to itself. The discussed points are standardization procedures and language performance treatment. The main question is how C++ will evolve further and if we should expect some drastic changes.

Inline – not what it used to be

Martin Vorbrodt wrote an article about the inline keyword and its new areas of applicability. It has been a part of the language for a long time to assist with non-violation of ODR and for runtime performance gains, sometimes at the cost of the size of the executable. The author noted that while inline can be ignored by the compiler, you can always define a function as a macro and have a preprocessor evaluating and substituting the code for it prior to compilation.

C++17 inline also helps with global variables shared across multiple compilation units. When defined in such a way, a variable can be included in multiple source files. The linker will guarantee that the same variable at the same memory location is accessed or modified regardless of which compilation unit it happens in. The same applies to static member variables of a class or struct.

Memory allocators and bad API

A new article by Jonathan Müller discusses memory allocators and issues in their current API. In the good API, functions request all required information as input parameters and return as much information as they are capable of providing. However, Malloc, free, calloc, and realloc functions do not follow this principle. The practical issues with these functions, as highlighted by the author, are:

  • Missing the ability to specify a custom alignment for the aligned memory.
  • The current implementation relies on the metadata about the allocator stored additionally.
  • There could be more memory allocated than we actually need and functions like malloc don’t report the actual size of the allocated memory block.
  • The automatic memory copy in realloc relies on a simple std::memcpy call and can’t help with invoking a move constructor or deal with self-referential pointers inside the object being copied.

Jonathan proposed a better interface to address these issues. He also shared recent improvements in this direction that have been suggested for or implemented in the language. This includes C++17 aligned allocation, sized deallocation, and a new allocate_at_least function in C++23 std::allocator.

Using the C++23 std::expected type

Marius Bancila dedicated an article to a new feature coming in C++23 – std::expected. This type is intended for situations when you need to return data from a function, but also when you want to indicate and explain an error without returning the data.
How can you do that now, before C++23 is released?

  • Return the data via a parameter passed by a reference and return a status code from a function.
  • Throw an exception in case the function fails.
  • Use C++17 std::variant. In this case the return type will be for both at the same time, a data and a status code. The usage in this case requires a rather complex syntax with std::visit.
  • Another option is std::optional. In this case, the return type may or may not contain a value. However, there is no way to explain the error and share the reason for failure in this implementation.

std::expected is a combination of std::variant and std::optional. So, it’s a union that either holds data or the failure. The blog post presents a solution to the same use case via std::expected.

Writing an open-source C++ static analysis tool

Check out this guest post from Greg Utas at C++ Stories. It’s dedicated to writing an open-source code checker with quick-fixes for C++ code. The idea was born from the requirement to clean up the #include directives on a project. This meant removing unnecessary headers and only including those that were being picked up transitively, but accidentally.
Google’s Include What You Use was not ready at that time, so Greg decided to create his own tool. It was later extended to to make recommendations about forward declarations and using declaration statements. Finally, quick-fixes made it to the tool, as it’s hard to imagine a useful checker without the ability to fix issues automatically.

The article doesn’t go into implementation details. The tool is built on RSC, an open-source framework for resilient C++ applications, and it supports the C++ language features that RSC uses – a subset of C++11. You can learn how to use the tool from the article, as it presents the CLI commands to use the tool and a practical example.

There are many tools in the ecosystem to compare with nowadays. The limitations of the current tool is also listed in the blog post. Which code analysis tool(s) do you use in your daily C++ development, if any?

Writing daemons in C++20

Many of us have written a simple daemon that sits and does some background job until shut down. An interesting point here is that most common code can’t properly handle the kill signal sent by entering Ctrl+C on the console. This article talks about the C++20 std::stop_source and std::stop_token, which help to implement a graceful shutdown. The full code example can be found in the article and is only provided for Windows, though implementation is also possible on Linux and macOS.

Simplify code with if constexpr and concepts in C++17/C++20

Another blog post in C++ Stories, written by Bartlomiej Filipek, is dedicated to if constexpr and concepts usages. It shares several handy examples where the enable_if approach is changed to if constexpr and concepts, making the code much more readable and expressive.
The examples used in the article are:

  • A function that gets two numbers and compares them. Floating and other numbers are treated differently here.
  • A function that takes a vector of numbers and returns their average value. The example doesn’t rely on C++20 ranges, instead demonstrating the if constexpr approach.
  • An example from Scott Meyers’ Effective Modern C++ book with a factory method that creates derived classes and supports a variable number of arguments for them.
  • A real-life example from a Microsoft implementation of standard library. The change gets rid of tag dispatch in the std::pair implementation.

Every example in the article starts with the known implementation via enable_if and then upgrades to if constexpr. Concepts are added to make the final code even more expressive.

Bool in C++ for function parameters

Antoine Morrier started a discussion about using booleans in function parameters. He suggests using an enum class instead to make sure the code is readable and functions are called correctly. Many readers noted in the comments that there is a bigger problem hidden in the text: using constant literals instead of symbolic names and passing multiple variables of the same type as parameters. As possible solutions, strong types, Named Parameter Idiom, and designated initializers are suggested. What would your solution be?

An interview about InfiniTime

In this interview, we talked to Jean-François Milants, the main contributor to the InfiniTime project, open-source firmware for the Pine64 PineTime smartwatch. He told us about starting the project and growing to six core developers and more than 100 contributors from all around the world. We discussed other platforms to which the software was ported, the Nordic Semiconductor nRF52832 microcontroller on which the PineTime smartwatch is based, how well it suits the smartwatch use-case, and how easy it is to get started.

The firmware currently uses C++14, with constexpr, the enum classes, move semantics, and other features widely used. It’s also built around many other open-source projects like FreeRTOS. We talked about them and about CLion, which Jean-François used to contribute to the project.

Remote C++ development with CLion

In July, we hosted a webinar dedicated to various setups for remote C++ development supported in CLion, JetBrains’ cross-platform C++ IDE. Matt Ellis and Timur Doumler discussed options like remote development with Gateway and remote development with local sources, WSL and Docker setups and dedicated toolchains, and collaborative editing with Code With Me. The speakers blinked a Raspberry Pi LED by debugging remotely from CLion, and even did that collaboratively (Matt blinking an LED on Timur’s side).

The follow-up blog post makes the recording of the webinar available, provides a collection of useful links for further reading and to the documentation, and presents some notable questions and answers from the event. For example, you can learn if the thin client inherits the CLion settings, or how privacy is guaranteed for Code With Me and Gateway.

CMake 3.24

The new CMake release brought many valuable changes. Read through the main highlights and check out the full release notes if you are interested.

  • Arm64 architecture is becoming more popular in the Windows world. For the new CMake version, a precompiled Windows arm64 binary is now provided.
  • With CMake 3.24, the environment variables like CC and CXX are not set when the corresponding language is enabled. Before that, they were only defined at configure time, not build time, and not set on consequent CMake runs. This change fixes the potentially different behavior between the first and subsequent CMake runs.
  • The CMAKE_COLOR_DIAGNOSTICS variable was added to control color diagnostics generated by compilers. This change was introduced by the CLion team and made it possible to get colorized Ninja output in CLion.
  • CMake Presets were upgraded to schema version 5.

The other changes include improvements for Green Hills MULTI and Visual Studio generators, along with many new commands, properties, variables, and other enhancements.

CLion 2022.2

At the end of July, a new version of CLion was released. This release is still aimed at improving many of the existing features and integrations and polishing the user experience, performance, and other aspects. The special focus on the code readability was the driver for some of the new features:

  • CLion 2022.2 gets Quick Documentation enhanced with the values of the expressions evaluated at compile time, enum values, and information about copy and move operations for the given class. Quick Documentation was also enabled for CMake scripts.
  • The naming scheme for CMake profiles auto-generated from CMake presets was updated.
  • Colorized Ninja output was supported in CLion, while being only available for CMake v3.24 and newer. CLion 2022.2 bundles CMake v3.23.
  • Bundled versions of the debugger were updated to GDB v12.1 and LLDB v14. And symbol server support was introduced for Windows.
  • Static code analysis was enriched with the Array index is out of bounds check.

Many performance improvements for various toolchains were introduced in the new version, including Space and IntelliJ Rust plugins updates and more. If you are interested in what the CLion team is up to in v2022.3 check out the roadmap announcement.

ReSharper C++ 2022.2

JetBrains ReSharper C++, an extension for Visual Studio for C++ developers, also got a 2022.2 update. It improves the C++ support quality and brings more productivity-boosting features for Unreal Engine-based game developers.

  • Blueprints support was previously only available in JetBrains Rider. Now, the integration has been introduced in ReSharper C++. The idea is that it reads Blueprints and introduces a new type of hint to help you see how Blueprint designers use and extend the baseline system implemented in the C++ part of Unreal Engine games.
  • By adding caching for precompiled headers, we managed to significantly improve the indexing speed. This is notable on the Unreal Engine code base and you can find the numbers in this blog post.
  • The new update comes with the bundled Clang-Tidy binary from Clang 14, adding new checks from the latest LLVM release.

Other changes include better handling of emplace– and make-like function calls, support for Spec unit tests, and syntax highlighting in the error tooltips.

LLVM 15

The new release groups many changes in LLVM, Clang, ClangFormat, Extra Clang Tools, and other parts of the LLVM ecosystem under v15.0.0. You might be interested in different parts of the announcement, so make sure to check it out. Here are the highlights noted by our team:

  • Clang compiler comes with many improvements for C++20 compliance. We’d like to specifically mention implementation of __builtin_source_location(), which enables library support for std::source_location. This library class represents certain information about the source code, such as file names, line numbers, and function names. It helps you avoid macros like __LINE__ and __FILE__ in your code. The new release included many changes required for C++20 Modules support in Clang, including the new mangling scheme, ABI isolation for member functions, Merging Modules proposals, and more.
  • LLVM v15.0.0 brings faster implementation for cross-translation unit analysis in Clang. It reduces the slow-down to around 2x compared to the single TU analysis. Previously, the slowdown on C++ projects could be up to 10x–12x.
  • ClangFormat changes are important to note if you are relying on changed parameters in your configurations. For example, IndentRequires was renamed to IndentRequiresClause and the default value was updated, and BreakBeforeConceptDeclarations now takes an enum instead of a boolean value.
  • Extra Clang Tools introduced updates for inlay hints, diagnostics, semantic highlighting, and code completion. Clang-Tidy came with fixes for the format of Checks and CheckOptions entries.
image description