# Simple C++20 input and output iterators

Sometimes I find myself rewriting a snippet often enough that I realize I should just blog it; this is one of those times.

Here’s a simple way to type-erase arbitrary sources and sinks into C++20 input iterators and output iterators.

# Always read the first error message first

In training classes, one of the things I always say (besides “Ask questions!”) is “Always look at the first error message, not the last one.” It’s so tempting to look at the last line of the compiler’s output first: after all, it’s the one that’s right there in front of you when the compiler finishes running. You think, “Well, I need to fix all the errors at some point anyway; might as well start here.” It’s a trap! Suppress that temptation, and scroll up to the first error message first.

# P1967 #embed and D2752 “Static storage for initializer_list” are now on Compiler Explorer

C++26 has adopted JeanHeyd Meneide’s proposal P1967 “#embed, which will allow C++ (and C) programmers to replace their use of the xxd -i utility with a built-in C preprocessor directive:

unsigned char favicon_bytes[] = {
#embed "favicon.ico"
};


# Happy birthday, Donald Knuth! and lamp-trolls

Today (January 10th) is Donald Knuth’s 85th birthday. Happy birthday, Dr. Knuth!

# In search of Adventure ]I[ (1981-ish)

As readers of this blog may know, I’m interested in digging up old text adventures and other games that have been “lost.” My one success story so far is Castlequest (1980); I’m still searching for David Long’s Adventure (LONG0751), Bob Maples’ Blackdragon, Dor Sageth, The PITS, and anything on this list. (If you have any information on any of these, please email me!)

# Pangrams and Scrabblegrams

Augustus De Morgan’s A Budget of Paradoxes contains these pangrams, which use each letter of the English alphabet once each. Being happily an inhabitant of Ye Olden Times, he gets to cheat by using “u” for “v” and “i” for “j” — two extra vowels, and two of the hardest consonants gone!

# Milner’s lamp

Quoted in “Problems for Solution,” American Mathematical Monthly 28:4 (April 1921):

In the Journal of the Indian Mathematical Society, June 1920 […] A. Narasinga Rao [proposes]: “Determine generally the form of a vessel whose contents are just spilling over in the position of equilibrium, whatever the amount of liquid it contains, (1) when it rests on a horizontal plane; (2) when it is suspended about a horizontal axis.”

This problem is known as “Dr. Milner’s lamp,” after Isaac Milner (1750–1820), Dean of Queen’s College, Cambridge. Milner’s having designed an idiosyncratic lamp is mentioned in the biography written posthumously by his niece, although she doesn’t imply anything mathematically interesting or ideal about the lamp’s shape, merely that it was a well-crafted reading lamp popular among Milner’s colleagues. (As a Fellow of the Royal Society, Milner corresponded with Sir Humphry Davy (1778–1829), inventor of a useful lamp of his own.)

# Hash-colliding string literals on MSVC

In my never-ending quest to make C++ braced initializers {1,2,3} behave more like string literals "abc" (see span should have a converting constructor from initializer_list (2021-10-03), which became P2447; and see my upcoming D2752 “Static storage for braced initializers”), I’ve been looking at how different compilers mangle the symbols for hidden variables such as the guard variables of static locals, the backing variables of structured bindings, and so on. This also led me to look at how the character arrays backing string literals are emitted by different compilers.

# Benchmarking Clang’s -fbuiltin-std-forward

In 2022 we saw a lot of interest (finally!) in the costs of std::move and std::forward. For example, in April Richard Smith landed -fbuiltin-std-forward in Clang; in September Vittorio Romeo lamented “The sad state of debug performance in C++”; and in December the MSVC team landed [[msvc::intrinsic]].

Recall that std::forward<Arg>(arg) should be used only on forwarding references, and that when you do, it’s exactly equivalent to static_cast<Arg&&>(arg), or equivalently decltype(arg)(arg). But historically std::forward has been vastly more expensive to compile, because as far as the compiler is concerned, it’s just a function template that needs to be instantiated, codegenned, inlined, and so on.

Way back in March 2015 — seven and a half years ago! — Louis Dionne did a little compile-time benchmark and found that he could win “an improvement of […] about 13.9%” simply by search-and-replacing all of Boost.Hana’s std::forwards into static_casts. So he did that.

Now, these days, Clang understands std::forward just like it understands strlen. (You can disable that clever behavior with -fno-builtin-strlen, -fno-builtin-std-forward.) As I understand it, this means that Clang will avoid generating debug info for instantiations of std::forward, and also inline it into the AST more eagerly. Basically, Clang can short-circuit some of the compile-time cost of std::forward. But does it short-circuit enough of the cost to win back Louis’s 13.9% improvement? Would that patch from 2015 still pass muster today? Let’s reproduce Louis’s benchmark numbers and find out!

# Copy semantics, per Plato’s Sophist

In Plato’s Sophist (translated by Nicholas P. White) we find this exchange between Theaetetus and the visiting philosopher. The visitor asks Theaetetus a question I’ve been asked many times: What do we mean by copy?

# Replacing std::lock_guard with a factory function

Recently I had to track down a use-after-free bug (which see) in some code that used librdkafka. The gist of it was: We call rd_kafka_new and pass it an rk_conf object containing a bunch of pointers to callbacks. rd_kafka_new either succeeds, in which case it gives us back a valid rd_kafka_t* and we make sure to keep those callback objects alive; or it fails (e.g. due to invalid configuration or resource exhaustion), in which case it gives us back NULL and we throw a C++ exception (and destroy those callback objects). But — here’s the bug, as far as I was able to tell — sometimes rd_kafka_new spawns a broker thread and then returns NULL anyway, without cleaning up the broker thread. And then later on, the broker thread attempts to call one of those callbacks… which we’ve already destroyed, because rd_kafka_new had told us it failed! So that was our use-after-free issue.

This use-after-free bug announced itself via an unusual symptom: an uncaught std::system_error exception.

# Polyomino strips, snakes, and ouroboroi

Previously on this blog: “Polycube snakes and ouroboroi” (2022-11-18).

Preparing to add the sequences from that post into OEIS, I realized to my surprise that most of the 2D analogues weren’t yet in OEIS either! There are several near-miss variations, though, involving the following concepts:

# Techniques for post-facto multiple inheritance

The other week on the std-proposals mailing list, TPK Healy asked for a way of dealing with the following classical-polymorphism scenario, which arises when dealing with wxWidgets.

# Polycube snakes and ouroboroi

In the June 1981 issue of Scientific American (JSTOR; direct link for Wikipedia users) Martin Gardner’s “Mathematical Games” column is titled “The inspired geometrical symmetries of Scott Kim.” Readers of this blog will remember Scott Kim as the creator of many fantastic ambigrams: “Scott Kim’s rotational ambigrams for the Celebration of Mind” (2020-10-18). Most of Gardner’s column indeed focuses on that part of Kim’s oeuvre. But the bit that piqued my interest this week was the following space-filling puzzle:

First we must define a snake. It is a single connected chain of identical unit cubes joined at their faces in such a way that each cube (except for a cube at the end of a chain) is attached face-to-face to exactly two other cubes. The snake may twist in any possible direction, provided no internal cube abuts the face of any cube other than its two immediate neighbors. The snake may, however, twist so that any number of its cubes touch along edges or at corners. A polycube snake may be finite in length, having two end cubes that are each fastened to only one cube, or it may be finite and closed so that it has no ends. A snake may also have just one end and be infinite in length, or it may be infinite and endless in both directions.

We now ask a deceptively simple question. What is the smallest number of snakes needed to fill all space?

# What I’m reading lately: tunnel edition

I’ve been working my way through Best Stories of H.G. Wells (Ballantine, 1960); this morning I read “The Story of the Late Mr. Elvesham” (1897). Highly recommended. It’s got the sort of elaborate Victorian sentence structure and overabundance of novelistic detail that can be delightful when it’s in service of a good plot, and frustratingly plodding when it’s not. In this case, it is. No spoilers.

# Refactoring with =delete

Pro tip: I’ve found =delete quite a useful tool when refactoring overly complicated overload sets in legacy code. Suppose we have an overload set in some legacy code that looks like this:

void foo(const char*, int, bool = false);  // #1
void foo(const char*, bool = false);       // #2
void foo(int, bool = false);               // #3


We suspect that overload #1 is unused. We comment it out, and the codebase still compiles, so we think it’s safe to remove.

Recently on the std-proposals mailing list, Madhur Chauhan proposed that C++ needs a better way to find the first set bit in an arbitrary-length bit-string. Today, if you want to manipulate bit-strings of length N, you have these options: