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. Contracts is forwarded to wording review, while still being fiercely opposed by some. Profiles is essenti...| www.foonathan.net
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 overlooked.| foonathan::blog()
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++.| foonathan::blog()
Last week, I’ve attended C++Now 2024 and it was definitely one of the best conferences I’ve ever been to!| foonathan::blog()
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.| foonathan::blog()
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.| foonathan::blog()
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.| foonathan::blog()
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. namespacetc{template<typenameRng>constexprautosize(Rng&&rng);// runtime-size of a range, like std::ranges::size template<typenameRng>requirestc::has_constexpr_siz...| foonathan::blog()
… and use lambdas instead? That is, instead of: intsum(inta,intb){returna+b;} You’d write: constexprautosum=[](inta,intb)->int{returna+b;}; Hear me out.| foonathan::blog()
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.| foonathan::blog()
(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 behavior. Still, I think there is room for innovation here. Let me talk about three new families of integer type...| www.foonathan.net
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 for memory allocation. Let’s talk why.| www.foonathan.net
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 are ways you can structure your CMake project to improve the experience for end users that use FetchContent: hi...| www.foonathan.net
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.| www.foonathan.net
The size of std::array is known at compile-time given the type. Yet it only provides a regular .size() member function: template 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.| www.foonathan.net
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 and std::string_view represent the same platonic value — we match Tony van Eerd’s criteria for impli...| www.foonathan.net
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 additional parameter. Let’s look at it in more detail.| www.foonathan.net
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 I’ve been thinking about in the past myself, and to my knowledge it hasn’t been done in any low-level language ...| www.foonathan.net
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 x? Or volatile_store(ptr, value) vs. volatile int*? When should you provide functions that implement new behavior and when should you write a wrapper type? Let’s look at the pro and cons.| www.foonathan.net
I thought the last release has taken a long time, this one took even longer for less changes! But now foonathan/memory is finally released. This time things get low-level to allow a better high-level. foonathan/memory is a library providing various memory allocators and adapter classes. Those allocators use a new RawAllocator concept that is simpler than STL’s Allocator and allows better control over the allocation aspect. Adapters and traits ensure compatibility with the existing model, al...| www.foonathan.net
As of version 0.5 my memory library now provides support for system-wide installation and CMake’s find_package(). Because I’ve spent hours of trial and error to come up with it, I’ll document it here. In this post, I will show you how to install your library so that it can be used easily by other projects. In particular, the system will be able to handle multiple installed versions and multiple configurations. Throughout this post, I’ll be assuming a 3.x CMake version and an already e...| www.foonathan.net
Last Tuesday I took a closer look at the Concept TS. This followed a discussion about the power and usefulness of concepts regarding a replacement for TMP (shout-out to @irrequietus and @Manu343726). So after compiling the GCC trunk that has concept support, I’ve specifically looked in a way to use concepts alone for doing arbitrary calculations. Attention: This is completely pointless. You’ve been warned. For that, I tried to implement a Prime_number concept that checks whether a given n...| www.foonathan.net
This series shares some lessons about optimizations especially regarding allocators starting with the general algorithm and profiling results/structure.| www.foonathan.net
This series shares some lessons about optimizations especially regarding allocators. This part gives you some guidelines regarding the very powerful inlining optimization.| www.foonathan.net
This post discusses some C++ propsals regarding allocators. It also gives more explanatation to the reasons behind the propagate_on_container_XX traits and talks about node sizes.| www.foonathan.net
This series shares some lessons about optimizations especially regarding allocators. This part covers branches.| www.foonathan.net
This series shares some lessons about optimizations especially regarding allocators. This part covers abstraction design and explains the importance of smart algorithms.| www.foonathan.net
This post explains why documenting C++ is hard and provides a solution.| www.foonathan.net
This post briefly describes my experience with issue driven development.| www.foonathan.net
This post describes final and explains why it can have negative consequence if you use final classes.| www.foonathan.net
This post describes possible reasons for using final classes.| www.foonathan.net
standardese version 0.1 comes with a better and more robust parsing as well as some other nice features.| www.foonathan.net
This post describes techniques for libraries to allow both exceptions and non-exceptional use. One is a technique I dubbed exception handler.| www.foonathan.net
This tutorial describes a simple way to handle external dependencies for C++ projects. It only uses native CMake and git, doesn't require any external package managers and is completely transparent for the user.| www.foonathan.net
Move safety is an easy way to classify the postcondition of a move operation, i.e. the moved-from state. Similar to exception safety there are four levels of safety: No-move, strong and basic move guarantee and destructive move.| www.foonathan.net
standardese version 0.2 comes with many features that make it a more mature tool like entity linking, index generation, more output formats and a completely changed comment system| www.foonathan.net
When introducing move operations to a class they make it possible to get invalid/empty objects. If your class previously ensured that all objects are valid, now that isn't possible anymore. This has consequences for interface design and it makes sense to introduce default constructors.| www.foonathan.net
If you have an error, you have to write code to deal with it. But how do you respond to the error? This post describes the various kinds of errors and how to react to them.| www.foonathan.net
The concept TS provides ways to define and require concepts in the C++ core language. But it doesn't really add anything besides syntax, everything is already possible in C++14 in a more or less nice looking way. How it is done is shown in this post.| www.foonathan.net
This post shows you how to write a generic and modular assertion macro. All code is available in the debug-assert GitHub library.| www.foonathan.net
This post shows you how the C++ type system can help you remove preconditions of functions and prevent errors.| www.foonathan.net
Type safe is a C++ header only library that provides zero overhead abstractions for better type safety. With it the techniques from the last blog post about preventing precondition errors are much simpler and safer to implement.| www.foonathan.net
Strong or opaque typedefs are typedefs that truly create new types instead of aliases. They are very useful to prevent accidental conversions and give more semantic meanings. This post shows you how they can be emulated in C++ today.| www.foonathan.net
If you want a function that returns multiple values, you'd use a reference and assign the outputs to that. But using a reference has a few drawbacks - it is not obvious in the caller, requires default construction etc. This post will explain why you sometimes need output parameters and how to fix their problems.| www.foonathan.net
If you're using a function template you don't need to pass in the arguments explicitly, the compiler can deduce them. But does this deduction always do what you want? Is there a way to prevent or require it?| www.foonathan.net
memory 0.6 will feature improved compositioning allocators to combine multiple allocators into one, as well as facilities to join multiple allocations into one.| www.foonathan.net
standardese 0.3 features member groups to re-use documentation, modules, inline documentation in the output, many minor improvements and a template mode to customize output and write additional files.| www.foonathan.net
std::initializer_list has a couple of flaws like its behavior combined with uniform initialization or generic functions. This post shows how they can be fixed or how to workaround the problems.| www.foonathan.net
If you have a function template and want to disable it for some properties on the template parameter, you can simply use SFINAE. But what if you have a non-template member function of a class template and want to disable it based on properties of the template? You can't use SFINAE then.| www.foonathan.net
Implementation of a variant is very interesting and a fun challenge. I've designed a generic and flexible variant class which is an improvement over std::variant, and want to share some of the design decisions.| www.foonathan.net
Sometimes you need to write code that can't use exceptions. If that's the case there isn't an obvious way to handle errors in constructors, as they don't have a return value. This post shows how you can report errors without using exceptions and without sacrificing the benefits of constructors.| www.foonathan.net
function_view is a simple type that can refer to any callable without overhead. However, the trivial implementation has issues with temporaries. In this post, we'll implement one that does not have these issues, while still keeping the same convenience. But this is harder than you might think.| www.foonathan.net
Policy-based design is great: It provides a lot of flexibility to the users of a class. They can use the exact policy for their use. However, it has a big problem: it creates a lot of different and incompatible types. This post explains it in more detail and discusses potential solutions.| www.foonathan.net
std::tuples can contain members of arbitrary types, and the standard library provides only accessors that need to know which element we want to have at compile time. In this post Arne will derive an implementation to access and iterate tuples at run time.| www.foonathan.net
This post shows how you can implement an alternative to flag enums with power-of-two-values in a way that is type-safe, easy and prevents common misuse of bitwise operators.| www.foonathan.net
std::string_view can be implicitly created from a temporary. This can be dangerous as a temporary might not live as long as the view object. So why is that? And is it a good idea? If not, how should it be instead?| www.foonathan.net
There is currently no great way to parse the C++ AST. libclang works for simple things, but is not feasible if you need more information. That's why I've created cppast.| www.foonathan.net
The preprocessor is a primitive text replacement tool inherited from C. Over the time, most usage became obsolete as better alternatives were added. So have we reached a point where it is feasible to get rid of the preprocessor? Completely?| www.foonathan.net
An old guideline is to prefer nonmember functions over member functions. But this can lead to some problems, so how true is it really? And can we solve this problems?| www.foonathan.net
Sometimes you calculate an expensive parameter and then the function don't need it at all! Examples would be the creation of a log message but the logger is disabled. With lazy evaluation of function arguments the parameter will only be evaluated when it is actually needed. But can we do it in C++?| www.foonathan.net
A discussion on Twitter got me thinking about operator precedence. It is a crucial part of most programming languages as it dictates the meaning of expressions. Interestingly enough, it is practically the same in almost all programming languages, even ones that radical try to be a better alternative for an established language. So apparently operator precedence is a solved problem, right? Well, I don’t think so. I think operator precedence is fundamentally flawed and could easily be improved.| www.foonathan.net
A moved-from object is left in a valid, but unspecified state. While this works, there are a couple of drawbacks to that design. So let's consider an alternative move, where a moved-from object is completely destroyed, not even its destructor will run. How could that work?| www.foonathan.net
You can mark constructors as explicit to prevent implicit conversions. But how should you handle assignment? Should you write an assignment operator as well?| www.foonathan.net
There are efforts to add 2D graphics to the C++ standard library. But should it be added? Or more general: when should something be added to the standard library?| www.foonathan.net
In the light of recent exceptions vs ADT discussion I wanted to share my thoughts, and offer a solution that combines the best of both worlds.| www.foonathan.net
The visitor pattern is a classical OOP pattern. It is used to solve the problem where you frequently want to add virtual functions to a class hierarchy, but rarely want to add new classes. However, it isn't particularly nice to use and doesn't fit the inheritance less trend of C++. So can we make it more modern and nicer to use?| www.foonathan.net
When creating new types, two interfaces are particularly important: How can the be created? And how do they convert to other types? Getting these two right makes your type much easier to use, so let's make some guidelines.| www.foonathan.net
I finally have found a way to manage my GitHub issues, it uses Trello combined with IFTTT and is surprisingly flexible.| www.foonathan.net
When should you use rvalue reference as function parameters? When as return types? And what are ref-qualified member functions and when should you use them?| www.foonathan.net
This post discusses the benefits and downsides of putting optional types in containers and possible alternatives.| www.foonathan.net
Let's revisit the question about optional in containers again because my previous post had some flaws. Mainly, I didn't realize that my use of vector differs from normal use. This points to an interesting new container.| www.foonathan.net
In my C++Now 2018 talk I introduced a taxonomy of pointer types in order to better formulate guidelines about using them. However, my taxonomy was badly named. Let's remedy that.| www.foonathan.net
This series explains the mathematical theory behind equivalence and ordering relations and gives an overview into the new three way comparison operator. This part it's all about equality.| www.foonathan.net
`std::optional`: do we need it and what are the semantics of `operator=`? I really quickly share my thought on the matter.| www.foonathan.net
This series explains the mathematical theory behind equivalence and ordering relations and gives an overview into the new three way comparison operator. This part it's about the math behind ordering relations.| www.foonathan.net
This series explains the mathematical theory behind equivalence and ordering relations and gives an overview into the new three way comparison operator. This part it's about implementing ordering relations in C++.| www.foonathan.net
This series explains the mathematical theory behind equivalence and ordering relations and gives an overview into the new three-way comparison operator. Now we finally talk about three-way comparison.| www.foonathan.net
This series explains the mathematical theory behind equivalence and ordering relations and gives an overview into the new three-way comparison operator. To finish we're talking about algorithms that can be implemented using three-way comparison.| www.foonathan.net
The new C++ spaceship operator has a couple of issues. Luckily, the latest mailing contains eleven proposals to fix them. Let's take a look.| www.foonathan.net
How do you setup CMake so it properly enables compiler warnings for your project? And how to prevent other code from getting warnings from your header files?| www.foonathan.net
`std::optional` means a `T` which might not be there. `std::optional>` means a `std::optional` which might not be there, so a `T` which might not be there, which might not be there. Is that the same as `std::optional` or something different?| www.foonathan.net
When should you write a destructor? When a copy constructor? Does it make sense to have assignment only? Quick guidelines: rule of zero, rule of three, rule of five, and everything else.| www.foonathan.net
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.| www.foonathan.net
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 name is a perfect description of what a function does, yet it is totally useless.| www.foonathan.net
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.| www.foonathan.net
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.| www.foonathan.net
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 auto add(H head, T... tail) { return head + add(tail...); } template auto add(H head) { return head; } However, C++17 added fold expressions, making it a one-liner: template auto add(H head, T... tail) { return (head + ... + tail); // expands to: head + tail[0] + tail[1] + ... } If we’re willing to abuse operator evaluation rules and fold ex...| www.foonathan.net
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 problematic for multiple reasons.| www.foonathan.net
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 produce the value. Then the variable is initialized on use and can also be made const. I’ve been recen...| www.foonathan.net
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 view constexpr as another platform you can target; it just so happens to be run by your compiler...| www.foonathan.net
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 by the normal function arguments. This leads to some interesting side-effects. In particular, def...| www.foonathan.net
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 good to a human user who wants something like line and column number to easily locate the problematic...| www.foonathan.net
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 not mean the class is actually std::is_trivially_copy_constructible or even std::is_copy_construc...| www.foonathan.net
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 parsing combinators which does not include punctuation, comments, or whitespace. Inspired by matklad’s blog...| www.foonathan.net
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 are directly available in the playground, to try it out and see what happens. While implementing this, I’v...| www.foonathan.net
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 predicates that check for well-formed syntax: every type that makes the syntax well-formed passes the predicate and thus m...| www.foonathan.net
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 CRTP interface technique and explore how it works.| www.foonathan.net
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 is a strict subset of a deterministic context free language, and so on. lexy, being essentially syntax suga...| www.foonathan.net
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 technique can be used whenever you want to specify some sort of “program” in a different way and trans...| www.foonathan.net