Blog

C++ Compile-Time Programming -- Wu Yongwei

logo.pngProgramming at compile time has been possible in C++ for a long time. Wu Yongwei considers its past, present and future.

Compile-time programming is a key feature of C++. It enables writing high-performance code often unattainable in other languages. This article explores its past, present, and future applications, highlighting the diverse possibilities in C++. We’ll briefly cover template metaprogramming, constexpr, variadic templates, static reflection, and more.

C++ Compile-Time Programming

by Wu Yongwei

From the article:

Compile-time programming is vastly different from run-time programming. The code runs during compilation, but the results can be used at run time.

Some believe compile-time programming is merely a trick, unused in real-world engineering. To them, I ask: do you use the C++ Standard Library? The mainstream implementations rely heavily on various programming techniques, including compile-time programming.

‘I don’t write the standard library’ – this might be a possible response. But consider this: the standard library is just one tool, a standard weapon. Is it enough to use only standard tools? That’s the real question.

The abundance of excellent open-source libraries suggests otherwise. A skilled programmer crafts tools for themselves and their team. If your work feels tedious, perhaps it’s time to build a bulldozer to tackle problems.

Compile-time programming offers a way to build such tools.

if constexpr requires requires { requires } -- Jonathan Müller

thinkcelllogo.pngProbably the two most useful features added to C++20 are requires and requires. They make it so much easier to control overload resolution, and when combined with if constexpr in C++17, they allow basic reflection-based optimizations in templates. While requires requires has gotten a lot of (negative?!) press for controlling overload resolution, its cousin requires { requires } is a bit overlooked.

if constexpr requires requires { requires }

by Jonathan Müller

From the article:

C++20 added requires, a way to enable or disable a function overload based on some compile-time condition. For example, consider a facility for producing debug output of types for error reporting:
thinkcellconst.png

The two overloads with the requires clause are only enabled for integers or floating point types, respectively, and are not considered otherwise. Additionally, overload resolution is smart: It knows that we want the overload with the most specific requirements, and it will only pick the first function when no other overload matches. This is also where concept comes in: A concept is simply a way to name a group of requirements that affects the search for more specific requirements. The technical term for that is subsumption. Because creating named requirements with concept also comes with additional syntax sugar, you don't need requires—so this blog post is gonna ignore concept. In general, if you would use a concept in only one place, it is too early to introduce it.

C++ programmer's guide to undefined behavior: part 9 of 11

Your attention is invited to the ninth part of an e-book on undefined behavior. This is not a textbook, as it's intended for those who are already familiar with C++ programming. It's a kind of C++ programmer's guide to undefined behavior and to its most secret and exotic corners. The book was written by Dmitry Sviridkin and edited by Andrey Karpov.

C++ programmer's guide to undefined behavior: part 9 of 11

by Dmitry Sviridkin

From the article:

And you could write it only in C++. In C, however, this mess has been forbidden (see 6.5.3.2, note 104). Also, you can't use the dereference operator on invalid and null pointers anywhere in C. Meanwhile, C++ has its own, special way of doing things. These weird examples were built in constexpr context (let me remind you that UB is forbidden there, and the compiler checks for it).

Implementing Trivial Relocation in Library -- Barry Revzin

TPWGDVRj_400x400.jpgOne of the reasons that I’m excited for Reflection in C++ is that it can permit you to implement, as a library, many things that previously required language features. In this post, I’m going to walk through implementing P2786R8 (“Trivial Relocatability For C++26”).

Implementing Trivial Relocation in Library

by Barry Revzin

From the article:

The goal here is not to say that the design is right or wrong (although the syntax certainly is suspect), but rather to show the kinds of things that reflection can solve.

We’ll just go straight to the wording and translate it into code as we go:

Trivially Relocatable Types

Scalar types, trivially relocatable class types (11.2 [class.prop]), arrays of such types, and cv-qualified versions of these types are collectively called trivially relocatable types.

This sure sounds like a type trait! Except in the world of reflection, those are just functions. How would we implement such a thing? We could start by doing this:

consteval auto is_trivially_relocatable(std::meta::info type)
    -> bool
{
    type = type_remove_cv(type);

    return type_is_scalar(type)
        or (type_is_array(type)
            and is_trivially_relocatable(
                type_remove_all_extents(type)
            ))
        or is_trivially_relocatable_class_type(type);
}

This is a fairly literal translation, where is_trivially_relocatable_class_type is something to be written shortly. But one interesting thing about the type_remove_all_extents type trait (i.e. std::remove_all_extents) is that it also works for non-array types, just returning back the same type. 

The Publish Pattern -- Lucian Radu Teodorescu

logo.pngHow do you minimise locking between producers and consumers? Lucian Radu Teodorescu describes a common, but currently undocumented, design pattern. Design patterns can help us reason about code. They are like algorithms that are vaguely defined in the code. Once we recognise a pattern, we can easily draw conclusions about the behaviour of the code without looking at all the parts. Patterns also help us when designing software; they are known solutions to common problems.

In this article, we describe a concurrency pattern that can’t be found directly in any listing of concurrency patterns, and yet, it appears (in one way or another) in many codebases. It is useful when we have producers and consumers that run continuously, and we want to minimise the locking between them.

The Publish Pattern

by Lucian Radu Teodorescu

From the article:

Let’s say we have an open-world game. As the player walks through the world, we load the data corresponding to the regions around the player. We have two types of workloads in our scenario: one for loading the data and another for displaying the loaded data. For the sake of our discussion, let’s say that each of these two activities is bound to a thread.

The problem we are trying to solve is how to structure the passing of data (let’s call this document) from the loading thread (producer) to the rendering thread (consumer). This is analogous to the classical producer-consumer problem [Wikipedia-1], but it has some interesting twists. Let’s try to outline the requirements of the problem:

  • (R1) The producer is constantly producing new versions of the document.
  • (R2) The consumer is constantly consuming document data.
  • (R3) The consumer will use the latest version of the document.

Please note that we are discussing multiple versions of the document. In our example, the loading thread will produce different documents depending on the position of the player, and the rendering thread will display the latest document, corresponding to the player’s most recent position.

 

C++ programmer's guide to undefined behavior: part 8 of 11

Your attention is invited to the eighth part of an e-book on undefined behavior. This is not a textbook, as it's intended for those who are already familiar with C++ programming. It's a kind of C++ programmer's guide to undefined behavior and to its most secret and exotic corners. The book was written by Dmitry Sviridkin and edited by Andrey Karpov.

C++ programmer's guide to undefined behavior: part 8 of 11

by Dmitry Sviridkin

From the article:

To avoid issues, use conditional noexcept always and everywhere and carefully check every function you use. Or don't use noexcept at all. In the second case, however, it's worth remembering that both move operations and swap should be marked as noexcept (and really be noexcept!) to effectively work with standard containers. Don't forget to write negative tests. You may miss a false noexcept and get std::terminate in the release build without them.

Standard C++ Foundation Annual Report for Fiscal Year 2024

FY2024 Annual Report – Standard C++ Foundation

(fiscal year ending 2024-06-30)

 

Highlights

This fiscal year FY2024 from 2023-07-01 to 2024-06-30. Although most of the Foundation’s work is done virtually, the pandemic did affect some of our prominent operations in 2020 through 2022. CppCon 2023 and 2024 have now been successfully held normally again fully on-site, and the pandemic's effects are now fully behind us.

As in every recent year, the majority of funds received and spent in FY2024 were from running CppCon.

As we came out of the pandemic, per our financial assistance policy the Foundation resumed spending on supporting in-person ISO C++ standardization. When the ISO C++ committee (WG21) resumed holding in-person meetings, with online Zoom participation, the pandemic had "spilled the pipeline" of planned hosts; the Standard C++ Foundation was instrumental in keeping WG21 meetings going, by paying in whole or in part for hosting three of the first four post-pandemic WG21 meetings, two of which fell into FY2023 and one of which will fell into FY2024. The Foundation will again host a WG21 meeting in November 2025 (FY 2026).

During FY2024, the Foundation again provided financial travel assistance to expert participants whose ISO C++ proposals had been encouraged by WG21 but who would not otherwise have been able to attend to progress their proposals; however, because WG21 meetings are now hybrid, participants who are able to present their papers remotely do not need travel assistance to attend the meeting.

Thank you very much once again to the Foundation's members and all the CppCon attendees and sponsors! Your support directly enables the Foundation to be able to pay for these ISO meetings and support ISO participants from around the world.

CppCon

Every year, the Foundation runs the CppCon conference, which is currently the largest C++ conference in the world. Since its inception in 2014, a goal for CppCon has been to help raise the bar for all C++ sister conferences. In our inaugural conference in 2014, we were the first C++ conference we know of to professionally record all talks and panels using a paid film crew, and make the videos available for free to everyone in the world; since then, several other conferences have followed suit, including that some have used the same video production company CppCon uses (Bash Films, which we can highly recommend). In each year since, we have continued to strive to add features, most recently professional in-room live captioning in 2019.

CppCon 2023 was held in October 2023, and CppCon 2024 in September 2024 (which is in FY 2025 but the information is now already available to report). Both enjoyed the highest number of talk submissions ever (second only to pre-pandemic 2019), and both years had year-over-year increases in attendees, sponsors, and exhibitors. We thank all our sponsors, exhibitors, volunteers, and attendees.

The professionally recorded C++ videos are made available worldwide at no charge on the CppCon YouTube channel. Here are some basic channel statistics updated for this fiscal year:

  • combined viewership: 20.5 million views (+4.1M views in the past year)
  • total watch time: 5.5 million hours (+600K hours in the past year)
  • channel subscribers: over 154,000 (+20K subscribers in the past year)

Next report

Our next annual report will cover the fiscal year from 2024-07-01 to 2025-06-30. Besides being published here, the annual report will also be given as usual as a live presentation at our annual Foundation members meeting which is held during the week of the autumn WG21 meeting.

About the Standard C++ Foundation

The Standard C++ Foundation (Standard CPP Foundation in some databases that don’t support + in names) is a Washington 501(c)(6) not-for-profit organization whose purpose is to support the C++ software developer community and promote the understanding and use of modern Standard C++ on all compilers and platforms. We do this by operating and funding isocpp.org, the github.com/isocpp and github.com/cplusplus repositories, the CppCon conference including CppCon.org and the CppCon YouTube channel, and providing financial assistance support for WG21 (ISO C++ committee) standards meetings for meeting hosting costs, travel assistance for attendees in financial need, and grants to progress WG21 proposals that have been encouraged but whose the authors cannot progress further without some financial assistance and that the WG21 major subgroup chairs have approved funding.

###

The “Standard C++ Foundation” name and stylized “C++” logo are trademarks of the Standard C++ Foundation. See isocpp.org/home/terms-of-use.

Smart Pointers and the Pointer to Implementation Idiom -- Andreas Fertig

me.pngA post I wrote back in 2023 When an empty destructor is required resulted in feedback that I'd like to address in today's post.

Smart Pointers and the Pointer to Implementation Idiom

by Andreas Fertig

From the article:

In the 2023 post, I briefly mentioned PImpl idiom. I did not intend to make it the theme of the post. However, I got various questions about PImpl and smart pointers.

The goal of PImpl is to hide implementation details from clients. Since you can declare a pointer of an unknown class, you can shift the entire implementation of such an anonymous class into a .cpp file. That way, no client can see any details. Another benefit is that changes to that .cpp file result in only minor recompiles. Maintaining the same in a header file would cause all .cpp files, including this header, to recompile. At least the speed-up part is since C++20's modules are no longer necessary. And as long as you don't want to hide classified implementation in the .cpp file modules, it also gives you the ability to mark constructs as private.

 

C++ programmer's guide to undefined behavior: part 7 of 11

Your attention is invited to the seventh part of an e-book on undefined behavior. This is not a textbook, as it's intended for those who are already familiar with C++ programming. It's a kind of C++ programmer's guide to undefined behavior and to its most secret and exotic corners. The book was written by Dmitry Sviridkin and edited by Andrey Karpov.

C++ programmer's guide to undefined behavior: part 7 of 11

by Dmitry Sviridkin

From the article:

In the early '70s, Ken Thompson, Dennis Ritchie, and Brian Kernighan worked on the first versions of C and Unix. They made a decision that resonates with pain, suffering, bugs, and inefficiency today, 50 years later. They decided that developers were to write strings—variable-length data—in a sequence that terminated with a null character. Assembly has it, and C should have it too, if people call it "high-level assembly"! After all, the poor old PDP has limited memory: it's better to have one extra byte per string than 2, 4, or even all 8 bytes (depending on the platform) to store the size... Nah, it's better to have a byte at the end! But even other languages store a size, a reference, or a pointer to the data...