Having Fun with Modern C++ -- Daniel Lemire

Jb7DBcxe_400x400.jpgRecent versions of the C++ language (C++20 and C++23) may allow you to change drastically how you program in C++. I want to provide some fun examples.

Having Fun with Modern C++

by Daniel Lemire

From the article:

Thanks to the integration of the features from the popular fmt library, it is much easier to format strings elegantly in C++. In turn the fmt library was inspired by the work done in languages like Python.

Suppose that you have a vector of integers and you want to print its content:

std::vector<int> v = {1, 2, 3, 4, 5};
std::println("{}", v);

Suppose you want it to be centered in a line of 40 characters, with underscore characters around it:

std::vector<int> v = {1, 2, 3, 4, 5};
std::println("{:_^40}", v);
// ____________[1, 2, 3, 4, 5]_____________

CopperSpice: std::launder

New video on the CopperSpice YouTube Channel:

std::launder

by Barbara Geller and Ansel Sermersheim

About the video:

Our recent C++ video started a lively conversation. We showed a use case for std::launder which caught several developers off guard. A new compiler setting was enabled which exposed a problem in our existing code. Please watch the full video to find out what we learned.

Take a look and remember to subscribe.

Trip Report: Meeting C++ 2024 -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGLast week, I got the chance to go to Berlin and participate in the 10th edition of Meeting C++ which is as far as I know the biggest C++ conference in Europe. Considering both the online and onsite participants, there were about 500 of us, eager to learn more mostly but not only about C++.

Trip Report: Meeting C++ 2024

by Sandor Dargo

From the article:

The conference was held in the East side of Berlin, in the Vienna House by Wyndham Andel’s Berlin Hotel offering some cool views of the city from its higher floors, especially from its sky bar. Not that we had a lot of time wandering in Berlin, the schedule was quite packed. Although the program only started around 9-10 AM depending on the day, the first two days the official program didn’t end before 10 PM.

Given the bit cold and cloudy weather, I realized that Berlin in November is really perfect for a conference. People will not be tempted to escape the venue for long walks outside. It just feels better to be inside.

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.