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.…
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…
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++.
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.
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.
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.
In my previous blog post , we’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’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 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’re writing generic code that expects some sort of compile-time sized range.
… and use lambdas instead? That is, instead of: int sum ( int a , int b ) { return a + b ; } You’d write: constexpr auto sum = []( int a , int b ) -> int { return a + b ; }; Hear me out.
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…
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’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.
Consider a library using hidden global state that needs to be initialized by calling an initialization function. If you don’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…
(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’s too much UB, others think it’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…
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 – they want to be a mostly drop-in replacement, but it’s still unfortunate because malloc() and free() are a bad API…
Last week, Chandler Carruth announced Carbon , a potential C++ replacement they’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. – but the thing I’m most excited about is a tiny detail about the way parameters are passed there. It’s something…
If you’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’s FetchContent module can do it for you. If you’re a library writer, there…
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’t handle recursive data structures, where one alternative contains the entire sum type again. Let’s see how we can fix that.
Suppose you want to do integer arithmetic that saturates instead of overflowing. The built-in operator+ doesn’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…
C++ constexpr is really powerful. In this blog post, we’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’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…
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’s look at the…
C++20 added concepts as a language feature. They’re often compared to Haskell’s type classes , Rust’s traits or Swift’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…
I’m currently rewriting the documentation for lexy , my C++ parser combinator library – 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…
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 “data” 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…
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…
I’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…
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…
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…
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 – immediately-invoked function expression – can be used: the variable is initialized by a lambda that computes the value, which is then immediately invoked to…
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’ve used them countless times in the past. However, they are functions . Plain, old, standard library functions. This is…
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 ,…
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 – sentinels.
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.
I wanted to write this blog post about (a specific part of) naming things back in July, but ironically I didn’t have a name for the symptom I wanted to describe. I only found a good name when I attended Kate Gregory’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…
Back in 2016, I started standardese , a C++ documentation generator. However, in the past two years I haven’t really worked on it. Now, I can officially announce that I have abandoned the project and transferred ownership. This blog post explains why.
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’t think the diagram is particularly useful for that, however. It covers way more combinations than actually make sense. So let’s talk about what you actually need to know about the special member functions and when you should…
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’s talk about them: What do they actually mean?
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’s talk about some other namespace feature, that is, well, not quite underrated, but relatively obscure: inline namespace. They are namespaces that don’t really introduce a scope, except when they do. So what…
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?
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’ve counted eleven of them that deal with the spaceship operator. So…
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 “induce a strict total ordering on the equivalence classes” 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…
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 “induce a strict total ordering on the equivalence classes” 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…
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 “induce a strict total ordering on the equivalence classes” 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…
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 “induce a strict total ordering on the equivalence classes” 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…
This should have been part 2 of my comparison series , and I have almost finished it, but due to university stuff I just haven’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’t know what I mean: std::optional<T&> doesn’t compile right now, because the…
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 “induce a strict total ordering on the equivalence classes” 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…
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’re an expert, you might get a deeper meaning from…
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’t able to respond to them earlier (note to self: don’t publish and then fly away to a conference), so I’m doing that now.…