Home
Barry's C++ Blog
Cancel

What's the right hash table API?

The Associative Container API When it comes to a hash table, there are basically only two interesting operations from an API perspective: lookup and insertion 1. The standard library containers are all very consistent in how these operations are provided, across all the associative containers (m...

Mutating through a filter

Introduction Nico Josuttis gave a talk recently that included an example like this: std::vector<int> coll{1, 4, 7, 10}; auto isEven = [](int i) { return i % 2 == 0; }; // increment even elements: for (int& i : coll | std::views::filter(isEven)) { ++i; // UB: but works } I want...

Prefer views::meow

With the adoption of Ranges in C++20 (and with a lot of new additions in C++23), we have a lot of new, composable, range-based algorithms at our disposal. There are, however, several ways to spell the usage of such algorithms: std::vector<int> v = {1, 2, 3}; auto square = [](int i){ return...

Getting in trouble with mixed construction

Several years ago, I wrote a post about the complexities of implementing comparison operators for optional<T>: Getting in trouble with mixed comparisons. That post was all about how, even just for ==, making a few seemingly straightforward decisions leads to an ambiguity that different libr...

Rust vs C++ Formatting

In Rust, if I want to print some 32-bit unsigned value in hex, with the leading 0x, padded out with zeros, I would write that as: println!("{:#010x}", value); In C++23, if I want to do the same, that’s: std::println("{:#010x}", value); The only difference is the spelling of the name of the ...

What's so hard about views::enumerate?

Sometimes, we want more than to just iterate over all the elements of a range. We also want the index of each element. If we had something like a vector<T>, then a simple for loop suffices 1: for (int i = 0; i < vec.size(); ++i) { // use i or vec[i] } But for a range that can’t be...

Copy-on-write with Deducing this

One of the new language features for C++23 is Deducing this, which is a feature I co-authored with Gašper Ažman, Sy Brand, and Ben Deane. The interesting history there is that Sy and I were working on solving one problem (deduplication of all the const and ref-qualifier overloads) and Gašper and ...

Assignment for optional<T>

Let’s talk about assignment for optional<T>. I realize this is a fraught topic, but I want to try to build up proper intuition about how assignment has to work, especially since the debate around this topic has been fairly underwhelming. This post will almost exclusively discuss copy assign...

Projections are Function Adaptors

There was a question recently on StackOverflow where a user was confused about the purpose of projections in a way that I think is fairly common. They wanted to do something like this: struct Person { std::string first; std::string last; }; std::vector<Person> people = { /* ... */...

Improving Output Iterators

Let’s say we had a range, represented by a pair of pointers, that we wanted to copy into another pointer. We might write that like so: template <typename T, typename U> void copy(T* first, T* last, U* out) { for (; first != last; ++first) { *out++ = *first; } } For trivia...