Blog

A shocking discovery about gcc’s unidirectional rotation algorithm -- Raymond Chen

RaymondChen_5in-150x150.jpgLast time, we looked at the rotation algorithm used by gcc libstdc++ for random-access iterators, and I concluded by noting that we’re going to make a shocking discovery.

Rotation revisited: A shocking discovery about gcc’s unidirectional rotation algorithm

by Raymond Chen

From the article:

As with all shocking discoveries, this one will shock disappoint you.

The discovery is that the gcc libstdc++ algorithm is the same as the forward-iterator algorithm!

Let’s run both algorithms on a problem where the two blocks are A1, A2, A3, B1, B2, B3, B4, B5. I’ll put the old forward iterator algorithm on top and the new gcc libstdc++ algorithm below.

first   mid       last
           
A1 A2 A3 B1 B2 B3 B4 B5
           
first   mid       last
 

We swap at first and mid, then advance both pointers. The two algorithms agree until first reaches the end of the original A block.

      first   mid   last
           
B1 B2 B3 A1 A2 A3 B4 B5
           
      first   mid   last
 

The old algorithm recurses in order to exchange A1, A2, A3 with B4, B4. This happens by exchanging A1 with B4 and A2 with B5.

Write, shorten, optimize

I stumble upon a C++ function that will be a really illustrative example of how refactoring can both shorten and optimize code. Today, we'll need to dust off our human brains in the era of vibe coding and recall what it's like to know what the good is and what the bad is—after all, someone has to do it.

Write, shorten, optimize

by Andrey Karpov

From the article:

Let's see how these implementations compare in reality. Designing a fair benchmark took a bit of effort. First, I had to ensure the input data couldn't overflow a 64-bit signed integer, since signed overflow is undefined behavior and would invalidate the measurements. Second, to make the contest fair, the test cases alternated between arrays with and without zero elements. Finally, the input arrays had varying lengths.

I'm not claiming that the measurements are rigorous, but they represent a general idea. The speed of the first original algorithm is taken as the baseline. I used Clang with the -O2 and -m64 options. The original version with two loops: 1. My version with a single loop: 0.88. The Claude version with a single multiplication: 0.92.

 

Rotation revisited: Another unidirectional algorithm -- Raymond Chen

RaymondChen_5in-150x150.jpgSome time ago, we looked at how to swap two adjacent blocks of memory in constant extra space, and along the way explored how std::rotate accomplishes the same task. I later claimed that the random-access implementations in both libc++ and libstdc++ treat the operation as a permutation decomposed into cycles—but after taking a closer look, I discovered that only libc++ does; libstdc++ uses a different algorithm altogether.

Rotation revisited: Another unidirectional algorithm

by Raymond Chen

From the article:

Some time ago, we looked at the problem of swapping two blocks of memory that reside inside a larger block, in constant memory, and along the way, we learned about std::rotate which swaps two adjacent blocks of memory (not necessarily the same size).

I noted in a postscript that clang’s libcxx and gcc’s libstdc++ contain specializations of std::rotate for random-access iterators that view the operation as a permutation and decomposes the permutation into cycles.

I was mistaken.

The implementation in gcc’s libstdc++ has special cases for single-element rotations, but in the general case, it uses a different algorithm.

Let’s call the blocks of memory to be exchanged A and B, where A is made up of elements A1, A2, A3, and so on; and block B has elements B1, B2, B3, and so on. Without loss of generality, suppose the A block is smaller. (If not, we can just mirror the algorithm.) And for concreteness let’s say that the elements are A1, A2, A3, B1, B2, B3, B4, B5.

C++ More C++26 reflection at compile-time -- Andreas Fertig

797f4c8c0b89b22b.pngIn today's post, I like touch-up on C++26's static reflection. In case you haven't seen, I wrote a first post C++26 reflection at compile-time a while ago.

C++ More C++26 reflection at compile-time

by Andreas Fertig

From the article:

One of the great things about reflection is that we can already explore the new feature since with Clang there is a compiler available that implements all the facets.

I was again exploring what of my use cases would be better solved with reflection. Now, one thing that I had to do most of my career is reading and writing data coming from a network connection. The definition of network was different at different times. What was common is, that everything going out was sent in network byte order (big-endian), and the everything that was received arrived in network byte order as well. For some systems there was no difference, as they where already big endian machines. But not all the time. Especially ARM pushed little endian. For a subset of the systems data had to be byte-swapped when it was received or sent.

How to swap data?

The issue here (was) is, how to swap the data? Every data type larger than a byte must be swapped every time. C++23 gave us std::byteswap which removes the need for the POSIX functions like htons. At least an improvement in terms of safety.

C++26 - Enter Static Reflection -- Keith Stockdale

headshot.jpgQuite recently it was announced that the release of GCC 16.1 brought in a load of C++26 reflection goodies. From looking at my LinkedIn, it seemed like everyone was extremely excited for this and a load of static reflection articles started popping up on my feed. This all got me a little excited to try it too, and I felt like this problem would be a good way to explore what static reflection has to offer.

C++26 - Enter Static Reflection

by Keith Stockdale

From the article:

Step 0: Figuring out how to even use reflection?!

As I mentioned, I had never used C++26 reflection, and I genuinely didn’t know how to even engage with it. I found CppReference to be quite lacking right now…

I am sure that will change as time goes on, but for right now, it’s a bit rubbish. So I found myself leaning on two other sources of information:

  1. The standard: Specifically Header synopsis. This was pretty damn great for just being able to find my way around all the facilities available. There are links to all the descriptions of what each facility does and what the expected behaviour is.
  2. Barry Revzin’s blog: Barry’s blog has some absolutely brilliant content around reflection, and I can’t recommend it enough.

C++26: More function wrappers -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGC++26 completes the type-erased callable wrapper picture. std::copyable_function gives us what std::function should have been from the start: a copyable wrapper with correct const semantics. std::function_ref fills the non-owning niche, offering a lightweight, zero-allocation alternative for callback parameters. Together with std::move_only_function, there’s no longer a reason to reach for std::function in new code.

C++26: More function wrappers

by Sandor Dargo

From the article:

C++26 continues to fill the gaps in our type-erased callable wrapper story. We already had std::function since C++11 and std::move_only_function since C++23, but there were still missing pieces. Now we’re getting two new additions: std::copyable_function and std::function_ref.

What’s wrong with std::function?

std::function has served us well, but it has two well-known issues. First, it can add significantly to binary size. Second, and more fundamentally, it has a const-correctness defect. 

C++26: Standard library hardening -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGLibrary hardening is one of those features that makes you wonder why it wasn’t standardized sooner. It catches real bugs, at negligible cost, across code you don’t have to change. The three major implementations have been doing their own versions of this for years — C++26 finally makes it portable and consistent.

C++26: Standard library hardening

by Sandor Dargo

From the article:

Undefined behavior (UB) in C++ is one of the hardest categories of bugs to deal with. It can silently corrupt memory, cause crashes far from the actual mistake, or — worst of all — just happens to work on your machine. A significant share of UB in real codebases comes not from exotic language features, but from basic misuse of the standard library: accessing a vector out of bounds, calling front() on an empty container, or dereferencing an empty optional.

C++26 addresses this directly with standard library hardening, introduced via P3471R4.

What is library hardening?

Library hardening converts certain undefined behavior in the standard library into detectable contract violations at runtime. When a hardened precondition is violated, the runtime reacts before any other observable side effect — think of it as adding bounds checking to operations that are UB today.

This is not a new idea. All three major standard library implementations already ship vendor-specific hardening modes. The problem is that these mechanisms are all different, non-portable, and inconsistently specified. P3471R4 standardizes what implementations already do.

The standardized version of hardening becomes the first use of contracts (specified in P2900). This aligns perfectly with the direction of the language.

BeCPP Symposium 2026 - Guy Davidson - Abstraction: The True Superpower of C++

BeCPP Symposium 2026 (organized by BeCPP): Now on YouTube!

Guy Davidson - Abstraction: The True Superpower of C++

Abstract:

The word "abstraction" is used extensively when discussing the facilities of C++. But what does it actually mean? Can you spot an abstraction when you see one? Can you spot the correct level of abstraction? Can you spot what is being abstracted? And what does a zero-cost abstraction mean? All these questions and more will be answered in this talk.

About the Speaker:

Guy Davidson is the convenor of the C++ standards committee. He is also the Head of Engineering at Six Impossible Things Before Breakfast. He has been writing games for nearly 50 years, having spent about half that time at Creative Assembly as the Head of Engineering Practice on the Total War franchise. He is the co-author of Beautiful C++, and you can find many of his talks online. In his copious free time, he plays the piano as well as singing first bass for the Brighton Festival Chorus. He lives in Brighton where he went to the University of Sussex back in the 80s.

 

From Undefined to Defined: Using std::launder in C++ -- Andreas Fertig

797f4c8c0b89b22b.pngIn today's post, I will continue with the overall topics of the last two months. Today you'll learn when and where you need to apply C++17's std::launder and where the difference to this utility is to reinterpret_cast or std::start_lifetime_as.

From Undefined to Defined: Using std::launder in C++

by Andreas Fertig

From the article:

The fields where you can apply today's learning vary. The embedded domain is usually one where std::launder is used, but if you're writing library code, laundering occurs as well.

When things may break

I'm using the example from the paper P0532R0:

struct X {
  const int n;  A
  double    d;
};

X* p = new X{7, 8.8};  B

new(p) X{42, 9.9};  C

int  i = p->n;  D
auto d = p->d;  E
You're looking at several different pieces that need to come together. Notice that the struct X declares the member n as const.

Next, with the help of new, an object is created in B and the resulting pointer is stored in p. So far, so good.

The interesting part starts next in C with the placement new. If you've never done this, great, then you might not need to do the laundry, at least not in your C++ code.

Save the Date: Pure Virtual C++ 2026

Pure Virtual C++ is back! For the 7th year running, Microsoft is hosting a free, one-day virtual conference for the whole C++ community.

Save the Date: Pure Virtual C++ 2026

by Marian Luparu

from the article:

Mark your calendar: Tuesday, July 21, 2026, starting at 14:00 UTC (7:00 AM in Seattle/Los Angeles, 11:00 AM in Buenos Aires, 10:00 PM in Hong Kong).