P2266’s interaction with decltype(auto)

C++Now 2021 is happening this week. Normally it’s in Aspen, Colorado, but this year it’s completely online. I presented two talks: “When Should You Give Two Things the Same Name?” and “The Complete Guide to return x.”

In my return x talk, slide 77 showed a table illustrating how P2266’s value-category changes affected five subtly different functions. One of the entries was incorrect; and, as I fixed it, I realized that for completeness the table should have included eight subtly different functions!

Here is a revised and I hope fully correct version of that table. …

Read More

Optimizing string::append is harder than it looks

Back in early March, Lukas Böger asked on StackOverflow: “Where do standard library or compilers leverage noexcept move semantics (other than vector growth)?” So I got nerdsniped into looking at all the places libc++ tests the noexceptness of any user-defined operation. This circuitously led to my finding an absolutely massive number of corner-case bugs in libc++’s string::append member function.

Read More

Antisocial Homeworlds, and a solitaire challenge

A couple of weeks ago, I came up with a new variant of Binary Homeworlds. Readers of this blog will already know Homeworlds as the “space chess” game played with colorful pyramids, invented by John Cooper, and popularized mainly by Andy Looney. In fact, this variant was directly inspired by a variant invented by Andy Looney in February 2021, which he called “Peaceful Homeworlds,” and which you can read about here.

Read More

Playing Castlequest (1980), Part 1

Earlier this week I posted that the source code for Castlequest (Holtzman and Kershenblatt, 1980) had been found — Castlequest exhumed!” (2021-03-09). By now it’s totally playable (at least if you have the ability to install GNU Fortran).

I had been seeking Castlequest because I had fond memories of the game on GEnie. I vaguely remembered the wandering werewolf, and the vampire in the attic that you have to kill with a tomato stake before the sun sets… But it turns out that the game is actually much much longer than I ever knew as a kid! I’m going to try the “All the Adventures” thing here, and describe my experience replaying the game this week.

This post contains major spoilers for all plot points and puzzles!

Read More

Escape analysis hates copy elision

Yesterday Lauri Vasama showed me this awesome Godbolt:

struct S {
    static std::unique_ptr<S> make() noexcept;

    static std::unique_ptr<S> factory() {
        std::unique_ptr<S> s = S::make();
        return M(s);

void take_ownership(S*) noexcept;

void test() {
    std::unique_ptr<S> p = S::factory();

When M(s) is defined as std::move(s), Clang gives pretty much optimal codegen for test: …

Read More

When can the C++ compiler devirtualize a call?

Someone recently asked me about devirtualization optimizations: when do they happen? when can we rely on devirtualization? do different compilers do devirtualization differently? As usual, this led me down an experimental rabbit-hole. The answer seems to be: Modern compilers devirtualize calls to final methods pretty reliably. But there are many interesting corner cases — including some I haven’t thought of, I’m sure! — and different compilers do catch different subsets of those corner cases.

Read More