RSSAmplifier

Blog

foonathan::blog()

Recent content on foonathan::blog()

foonathan.netRSS feed ↗109 posts

Latest posts

Trip Report: Fall ISO C++ Meeting in Wrocław, Poland

Last week, I attended the fall 2024 meeting of the ISO C++ standardization committee in Wrocław, Poland. This was the fifth meeting for the upcoming C++26 standard and the feature freeze for major C++26 features. For an overview of all the papers that made progress, read Herb Sutter’s trip report . Contracts and profiles are the big ticket items that made the most progress this meeting.…

if constexpr requires requires { requires }

Probably 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…

Trip Report: Summer ISO C++ Meeting in St. Louis, USA

Two weeks ago, I attended the summer 2024 meeting of the ISO C++ standardization committee in St. Louis, USA. We made progress on a lot of features for C++26, but I have some thoughts about senders/receivers, reflection, and the idea of introducing borrow checking to C++.

Trip Report: C++Now 2024

Last week, I’ve attended C++Now 2024 and it was definitely one of the best conferences I’ve ever been to!

Trip Report: Spring ISO C++ Meeting in Tokyo, Japan

Last week, I attended the spring 2024 meeting of the ISO C++ standardization committee in Tokyo, Japan. We made progress on a bunch of interesting features for C++26.

I'm the new assistant chair of SG 9, the study group for std::ranges!

In a week, the C++ standardization committee is meeting in Tokyo, Japan, to continue work on C++26. It will be my first meeting with an official role as assistant chair of SG 9.

C++ needs undefined behavior, but maybe less

The C++ standard does not specify all behavior. Some things are up to the implementation, while other operations are completely undefined, and the compiler is free to do whatever it wants. This is essential for some optimizations but can also be dangerous. The newly proposed erroneous behavior addresses it, but it cannot be used to eliminate all undefined behavior.

Compile-time sizes for range adaptors

In my previous blog post , we&rsquo;ve discussed the static constexpr std::integral_constant idiom to specify the size of a range at compile-time. Unlike the standard, our [think-cell&rsquo;s] ranges library at think-cell already supports compile-time sizes natively, so I was eager to try the idiom there and see how it works out in practice. namespace tc { template < typename Rng > constexpr auto…

The new static constexpr std::integral_constant idiom

The size of std::array<T, N> is known at compile-time given the type. Yet it only provides a regular .size() member function: template < typename T , std :: size_t N > struct array { constexpr std :: size_t size () const { return N ; } }; This is annoying if you&rsquo;re writing generic code that expects some sort of compile-time sized range.

Should we stop writing functions?

&hellip; and use lambdas instead? That is, instead of: int sum ( int a , int b ) { return a + b ; } You&rsquo;d write: constexpr auto sum = []( int a , int b ) -> int { return a + b ; }; Hear me out.

Constrain your user-defined conversions

Sometimes you want to add an implicit conversion to a type. This can be done by adding an implicit conversion operator. For example, std::string is implicitly convertible to std::string_view : class string { // template omitted for simplicity public : operator std :: string_view () const noexcept { return std :: string_view ( c_str (), size ()); } }; The conversion is safe, cheap, and std::string…

Trip report: Summer ISO C&#43;&#43; Meeting in Varna, Bulgaria

Last week, I attended the summer 2023 meeting of the ISO C++ standardization committee in Varna, Bulgaria. This was my first meeting since the pandemic and the first meeting as official member thanks to think-cell&rsquo;s participation in the German national body. In total, 18 different countries sent representatives and over 180 C++ experts attended, although some of them only remotely.

Technique: Proof types to ensure preconditions

Consider a library using hidden global state that needs to be initialized by calling an initialization function. If you don&rsquo;t call the function before you start using the library, it crashes. How do you design the library in such a way that it is impossible to use it before initialization? One idea is to use a technique where you create a special proof type , which needs to be passed as an…

New integer types I&#39;d like to see

(Most) C++ implementations provide at least 8, 16, 32, and 64-bit signed and unsigned integer types. There are annoying implicit conversions, discussions about undefined behavior on overflow (some think it&rsquo;s too much UB, others think it&rsquo;s not enough), but for the most part they do the job well. Newer languages like Rust copied that design, but fixed the conversions and overflow…

malloc() and free() are a bad API

If you need to allocate dynamic memory in C, you use malloc() and free() . The API is very old, and while you might want to switch to a different implementation, be it jemalloc , tcmalloc , or mimalloc , they mostly copy the interface. It makes sense that they do that &ndash; they want to be a mostly drop-in replacement, but it&rsquo;s still unfortunate because malloc() and free() are a bad API…

Carbon&#39;s most exciting feature is its calling convention

Last week, Chandler Carruth announced Carbon , a potential C++ replacement they&rsquo;ve been working on for the past two years. It has the usual cool features you expect from a modern language: useful generics, compile-time interfaces/traits/concepts, modules, etc. &ndash; but the thing I&rsquo;m most excited about is a tiny detail about the way parameters are passed there. It&rsquo;s something…

Tutorial: Preparing libraries for CMake FetchContent

If you&rsquo;re working on an executable project in C++, as opposed to a C++ library, using a package manager to get your dependencies might be overkill: If all you need is to get the source code of a library, include in your CMake project, and have it compiled from source with the rest of your project, CMake&rsquo;s FetchContent module can do it for you. If you&rsquo;re a library writer, there…

Technique: Recursive variants and boxes

There are many data structures that can be elegantly expressed using sum types. In C++ a (somewhat clunky) implementation of sum types is std::variant . However, it can&rsquo;t handle recursive data structures, where one alternative contains the entire sum type again. Let&rsquo;s see how we can fix that.

`saturating_add` vs. `saturating_int` -- new function vs. new type?

Suppose you want to do integer arithmetic that saturates instead of overflowing. The built-in operator+ doesn&rsquo;t behave that way, so you need to roll something yourself. Do you write a saturating_add() function or a new saturating_int type with overloaded operator+ ? What about atomic_load(x) vs. atomic<int> x ? Or volatile_store(ptr, value) vs. volatile int* ? When should you provide…

Technique: Compile Time Code Generation and Optimization

C++ constexpr is really powerful. In this blog post, we&rsquo;ll write a compiler that can parse a Brainfuck program given as string literal, and generate optimized assembly instructions that can then be executed at runtime. The best part: we neither have to actually generate assembly nor optimize anything ourselves! Instead we trick the compiler into doing all the hard work for us. The same…

I accidentally wrote a Turing-complete parsing library

I&rsquo;m currently working on lexy , a C++ parsing DSL library: you describe how input should be parsed , and lexy generates code for it, taking care of error recovery , parse tree generation , and parse values . Such parser generators are classified based on the expressiveness of the corresponding formal language . For example, a strict regular expression can only parse regular languages, which…

Tutorial: the CRTP Interface Technique

Generic code expects that your types model certain concepts. Sometimes, the concept requires many redundant member functions in your type. A big culprit here are iterators: they require many operator overloads, most of which are trivially implemented in terms of other overloads. CRTP, the curiously recurring template pattern, can help here and automate the boilerplate away. Let&rsquo;s look at the…

C&#43;&#43;20 concepts are structural: What, why, and how to change it?

C++20 added concepts as a language feature. They&rsquo;re often compared to Haskell&rsquo;s type classes , Rust&rsquo;s traits or Swift&rsquo;s protocols . Yet there is one feature that sets them apart: types model C++ concepts automatically. In Haskell, you need an instance , in Rust, you need an impl , and in Swift, you need an extension . But in C++? In C++, concepts are just fancy boolean…

Tutorial: Interactive code snippets with Hugo and Compiler Explorer

I&rsquo;m currently rewriting the documentation for lexy , my C++ parser combinator library &ndash; hey, this is the fourth blog post in a row mentioning it in the introduction! It already has an interactive online playground where you can enter a grammar and input and see the resulting parse tree and/or error messages. This is really helpful, so the new documentation will contain examples that…

Implementation Challenge: Lossless, compact parse tree with iterative traversal

My parser combinator library lexy was originally designed to parse some grammar into a user-defined data structure, comparable to Boost.Spirit . This is ideal for parsing simple &ldquo;data&rdquo; grammars like JSON or email addresses , and also works for parsing programming languages: simply parse into your AST. However, by design lexy::parse() will only forward data explicitly produced by the…

Trivially copyable does not mean trivially copy constructible

About a month ago, I got an interesting pull request for lexy , my new parser combinator library. It fixed a seemingly weird issue relating trivially copyable types and special member function of classes containing unions. While digging into it, I learned a lot about trivial special member functions and made a somewhat surprising realization: Just because a class is std::is_trivially_copyable does…

What is the unit of a text column number?

I&rsquo;ve recently published my parsing combinator library lexy . One of the things it does is issue a lexy::error if the input does not match the grammar. This error has a .position() which gives you the position where the error occurred. In order to keep the happy path fast, .position() is not something that is easy to use for end users: it is simply an iterator into the input range. This is no…

Tricks with Default Template Arguments

Just like regular function parameters, template parameters can also have default parameters. For class templates, this behaves mostly just like default function arguments: if you pass fewer template arguments than required, default template arguments are used to fill the remaining places. However, for function templates, it gets more complicated as template parameters for functions can be deduced…

`constexpr` is a Platform

Let me share a useful insight with you: constexpr is a platform. Just like you write code that targets Windows or a microcontroller, you write code that targets compile-time execution. In both cases you restrict yourself to the subset of C++ that works on your target platform, use conditional compilation if your code needs to be portable, and execute it on the desired target platform. You can thus…

Technique: Immediately-Invoked Function Expression for Metaprogramming

Common C++ guidelines are to initialize variables on use and to make variables const whenever possible. But sometimes a variable is unchanged once initialized and the initialization is complex, like involving a loop. Then an IIFE &ndash; immediately-invoked function expression &ndash; can be used: the variable is initialized by a lambda that computes the value, which is then immediately invoked to…

Implementation Challenge: Replacing std::move and std::forward

When C++11 introduced move semantics, it also added two important helper functions: std::move and std::forward . They are essential when you want to manually indicate that you no longer care about an object or need to propagate the value category in generic code. As such, I&rsquo;ve used them countless times in the past. However, they are functions . Plain, old, standard library functions. This is…

Nifty Fold Expression Tricks

Suppose you need to have a variadic function and want to add all arguments together. Before C++17, you need two pseudo-recursive functions: template < typename H , typename ... T > auto add ( H head , T ... tail ) { return head + add ( tail ...); } template < typename H > auto add ( H head ) { return head ; } However, C++17 added fold expressions , making it a one-liner: template < typename H ,…

Tutorial: C&#43;&#43;20&#39;s Iterator Sentinels

You probably know that C++20 adds ranges. Finally we can write copy(container, dest) instead of copy(container.begin(), container.end(), dest) ! Ranges also do a lot more. Among other things, they add a new way of specifying an iterator to the end &ndash; sentinels.

std::polymorphic_value &#43; Duck Typing = Type Erasure

I recently had an insight about type erasure that I wanted to share. Type erasure is a combination of two techniques working together to achieve both polymorphism and value semantics: std::polymorphic_value , a proposed standard library type, and duck typing.

Naming Things: Implementer vs. User Names

I wanted to write this blog post about (a specific part of) naming things back in July, but ironically I didn&rsquo;t have a name for the symptom I wanted to describe. I only found a good name when I attended Kate Gregory&rsquo;s talk on naming at CppCon, and now I finally have the time to write my thoughts down. So I want to write about naming. In particular, about the phenomenon that sometimes a…

Standardese Documentation Generator: Post Mortem and My Open-Source Future

Back in 2016, I started standardese , a C++ documentation generator. However, in the past two years I haven&rsquo;t really worked on it. Now, I can officially announce that I have abandoned the project and transferred ownership. This blog post explains why.

Tutorial: When to Write Which Special Member

When explaining someone the rules behind the special member functions and when you need to write which one, there is this diagram that is always brought up. I don&rsquo;t think the diagram is particularly useful for that, however. It covers way more combinations than actually make sense. So let&rsquo;s talk about what you actually need to know about the special member functions and when you should…

Nested Optionals, Expected and Composition

Andrzej wrote about problems with CTAD and nested optionals , then Barry wrote about problems with comparison and nested optionals . What do both problems have in common? Nested optionals. So let&rsquo;s talk about them: What do they actually mean?

Inline Namespaces 101

Almost three years ago — wow, how time flies — I blogged about namespace aliases and called them one of C++ most underrated features (which probably was a bit of a click bait). Let&rsquo;s talk about some other namespace feature, that is, well, not quite underrated, but relatively obscure: inline namespace. They are namespaces that don&rsquo;t really introduce a scope, except when they do. So what…

Tutorial: Managing Compiler Warnings with CMake

Warnings are important, especially in C++. C++ compilers are forced to accept a lot of stupid code, like functions without return , use of uninitialized warnings, etc. But they can at least issue a warning if you do such things. But how do you manage the very compiler-specific flags in CMake? How do you prevent your header files from leaking warnings into other projects?

Proposals to Fix the Spaceship Operator

I did a series about comparisons recently where I gave some guidelines about using the upcoming spaceship operator for three-way comparison. In particular, I pointed out a couple of flaws with the design as it is currently. Well, now the proposals for the next C++ standardization meeting are here — almost 300 of them. And I&rsquo;ve counted eleven of them that deal with the spaceship operator. So…

Mathematics behind Comparison #5: Ordering Algorithms

In order to sort a collection of elements you need to provide a sorting predicate that determines when one element is less than the other. This predicate must &ldquo;induce a strict total ordering on the equivalence classes&rdquo; according to cppreference . Wait, what? The upcoming C++ spaceship operator implements a three-way comparison, i.e. it is a single function that can return the results…

Mathematics behind Comparison #4: Three-Way Comparison

In order to sort a collection of elements you need to provide a sorting predicate that determines when one element is less than the other. This predicate must &ldquo;induce a strict total ordering on the equivalence classes&rdquo; according to cppreference . Wait, what? The upcoming C++ spaceship operator implements a three-way comparison, i.e. it is a single function that can return the results…

Mathematics behind Comparison #3: Ordering Relations in C&#43;&#43;

In order to sort a collection of elements you need to provide a sorting predicate that determines when one element is less than the other. This predicate must &ldquo;induce a strict total ordering on the equivalence classes&rdquo; according to cppreference . Wait, what? The upcoming C++ spaceship operator implements a three way comparison, i.e. it is a single function that can return the results…

Mathematics behind Comparison #2: Ordering Relations in Math

In order to sort a collection of elements you need to provide a sorting predicate that determines when one element is less than the other. This predicate must &ldquo;induce a strict total ordering on the equivalence classes&rdquo; according to cppreference . Wait, what? The upcoming C++ spaceship operator implements a three way comparison, i.e. it is a single function that can return the results…

Let&#39;s Talk about std::optional<T&> and optional references

This should have been part 2 of my comparison series , and I have almost finished it, but due to university stuff I just haven&rsquo;t found the time to polish it. But the optional discussion started again, so I just wanted to really quickly share my raw thoughts on the topic. In case you are lucky and don&rsquo;t know what I mean: std::optional<T&> doesn&rsquo;t compile right now, because the…

Mathematics behind Comparison #1: Equality and Equivalence Relations

In order to sort a collection of elements you need to provide a sorting predicate that determines when one element is less than the other. This predicate must &ldquo;induce a strict total ordering on the equivalence classes&rdquo; according to cppreference . Wait, what? The upcoming C++ spaceship operator implements a three way comparison, i.e. it is a single function that can return the results…

A (Better) Taxonomy of Pointers

At C++Now 2018 I gave a talk about rethinking pointers: jonathanmueller.dev/talk/cppnow2018 . I highly recommend you check it out, even if you watched the similar talk I gave at ACCU, as that version is a lot better. It rediscovers and discusses the common guidelines about when to use references over pointers, when smart pointers, etc. If you&rsquo;re an expert, you might get a deeper meaning from…

optional<T> in Containers Ⅱ — Not All std::vector Usages Are The Same

Okay, so in the previous post I talked about putting optional<T> in container. I came to conclusions which I though were reasonable at the time, however, people — rightfully — pointed out some flaws in my argumentation. As I was at ACCU last week, I wasn&rsquo;t able to respond to them earlier (note to self: don&rsquo;t publish and then fly away to a conference), so I&rsquo;m doing that now.…

Should You Put optional<T> in a Container?

Title says it all: should you put std::optional<T> in a container? To answer that we have to take a slight detour first.