<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss/styles.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Lesley Lai&apos;s Blog</title><description>Lesley Lai&apos;s blog only feed</description><link>https://lesleylai.info</link><language>en-us</language><item><title>A Love Letter to Flashcards</title><link>https://lesleylai.info/en/flashcards</link><guid isPermaLink="true">https://lesleylai.info/en/flashcards</guid><description>A personal reflection on how spaced repetition and hand crafted flashcards helps me to keep understanding alive</description><pubDate>Tue, 05 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This piece is a submission for &lt;a href=&quot;https://hamatti.org/posts/indieweb-carnival-write-a-love-letter/&quot; target=&quot;_blank&quot;&gt;IndieWeb Carnival May 2026: Write a love letter&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For a long time, flashcards were not on my radar for effective learning. I used it for English vocabulary when I was learning English as a teen, but I never considered using it for subjects that require deep understanding. When thinking about flashcards, an image that swiftly sprang to mind was of someone who mechanically memorizes definitions and equations, brute-forces through exams without comprehension. Such &lt;em&gt;rote memorization&lt;/em&gt; is indeed detrimental to learning. This sentiment is common in STEM fields. A quick search leads to &lt;a href=&quot;https://www.reddit.com/r/math/comments/jwi0do/how_do_you_use_flashcards_for_higher_level_math/&quot; target=&quot;_blank&quot;&gt;reddit posts like this&lt;span&gt;&lt;/span&gt;&lt;/a&gt; where higher upvoted answers dismiss the value of flashcards.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;My grandma was an expert in rote memorization. She didn’t have the opportunity to receive a basic education until she was 18, and she somehow passed exams as a semiliterate person by memorizing the content of whole essays, including punctuation! Later, she bulldozed through medical school and became the first college graduate in my family.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;My perception changed through the &lt;a href=&quot;https://www.coursera.org/learn/learning-how-to-learn&quot; target=&quot;_blank&quot;&gt;learning how to learn course&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, where I relearned about &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaced_repetition&quot; target=&quot;_blank&quot;&gt;Spaced repetition&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, the technique of reviewing topics at increasing intervals. Using spaced repetition as a general-purpose learning tool (rather than just for rote memorization of vocabulary) was perhaps the most important thing I learned from that course. The course also specifically mentioned &lt;a href=&quot;https://apps.ankiweb.net/&quot; target=&quot;_blank&quot;&gt;Anki&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, perhaps the most famous flashcard software, as a way to facilitate spaced repetition.&lt;/p&gt;
&lt;p&gt;I had a particular reason to take this seriously: my memory is terrible. I often even forget what I did the day before, and the same goes for things I’ve studied. Math is the worst. I learned it in intensive bursts, but I rarely use it day to day, and what I study now might not be useful for another five years. Naturally, calculus, linear algebra, probability, and even high school trigonometry have all quietly slipped away.&lt;/p&gt;
&lt;p&gt;It turns out that math is very cumulative: theorems built upon theorems. If I am not fluent in the basics, I will quickly be inundated with all the new material. There is a psychological concept called &lt;a href=&quot;https://en.wikipedia.org/wiki/Chunking_(psychology)&quot; target=&quot;_blank&quot;&gt;chunking&lt;span&gt;&lt;/span&gt;&lt;/a&gt; that describes the inverse of this: once one internalizes the basics, they can think at a higher level of abstraction. From this perspective, fields that require deep understanding, like math, require memory just as fields with a breadth of shallow knowledge do, though in different ways.&lt;/p&gt;
&lt;p&gt;Now you may think that with today’s abundance of information, we can look up everything pretty quickly. That is true. But the quickest search is slower than your brain. Moreover, not everything can be easily looked up, especially what falls into insights rather than definitions. When you look it up, you will only find lengthy articles to impart their wisdom, and that will take weeks to digest (again, if you have learned but forgotten).&lt;/p&gt;
&lt;p&gt;How do I actually use flashcards? My software of choice is Anki. I am not completely satisfied with it. The UI looks dated, the WYSIWYG HTML editor is clunky, and the undocumented file format makes potential porting and interoperability tricky. However, its ability to have a flexible card format is unparalleled. I’ve tried a few plain-text-based alternatives like Obsidian’s &lt;a href=&quot;https://stephenmwangi.com/obsidian-spaced-repetition/&quot; target=&quot;_blank&quot;&gt;Spaced Repetition plugin&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but they are not even remotely close to what I need.&lt;/p&gt;
&lt;p&gt;I don’t use spaced repetition to replace traditional learning. In fact, it takes up only a small portion of my total learning time. One thing that’s right about the “common sense” in the STEM fields is that without understanding, flashcards are useless. You need to understand the materials first, and reading flashcards written by others is a really poor way to do that. Two corollaries follow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;don’t memorize what you don’t understand&lt;/li&gt;
&lt;li&gt;prefer your own flashcards to other people’s flashcards, at least for fields that require deep understanding&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But once I understand something, flashcards are effective to keep the understanding alive.&lt;/p&gt;
&lt;p&gt;When I started making flashcards, I looked at many flashcard decks from other sources, such as &lt;a href=&quot;https://ankiweb.net/shared/decks&quot; target=&quot;_blank&quot;&gt;Anki’s Shared Decks&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and Quizlet, for inspiration. I found that most decks floating around on the Internet are of poor quality. They are usually definitions and facts semi-mechanically transcribed from a textbook.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Some people also use LLMs to generate flashcards. And of course, the result will be those impersonal, mediocre cards.&lt;/p&gt;
&lt;p&gt;I won’t say LLMs are useless for this. But from my trials, I get about 1 card that’s useful to me out of 10, and even that 1 card still needs rewriting.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;I do something different. Most of my cards are handwritten by me and accommodate my brain.&lt;/p&gt;
&lt;p&gt;While I have definition and fact cards, I also have many cards on intuition and “A-ha moments”. Those fade from memory, too, so it’s worth preserving them. Here is an example (feel free to skip if you are not familiar with the topic, but I intentionally picked something that I hope is easy to understand):&lt;/p&gt;

Q: What is the intuition that two reflections gives a rotation?
&lt;p&gt;A: Both reflection and rotations are &lt;strong&gt;orthogonal transformations&lt;/strong&gt;. The difference is that rotation preserves orientation while reflection flips it. If we apply the reflection twice, the first reflection flips the orientation and the second reflection flips it back. Also, if we apply multiple orthogonal transformations, the combined transformation is still orthogonal. Thus, at the end we get an orthogonal transformation that is orientation-preserving, which is a rotation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;rotation as two reflection&quot; loading=&quot;lazy&quot; width=&quot;257&quot; height=&quot;196&quot; src=&quot;/_astro/rotation_as_two_reflection.DUOfpCFn_Z2wydEN.webp&quot; /&gt;&lt;/p&gt;
&lt;p&gt;See:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://demonstrations.wolfram.com/RotationAsProductOfTwoReflections/&quot; target=&quot;_blank&quot;&gt;https://demonstrations.wolfram.com/RotationAsProductOfTwoReflections/&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.euclideanspace.com/maths/geometry/rotations/theory/as2reflections/index.htm&quot; target=&quot;_blank&quot;&gt;https://www.euclideanspace.com/maths/geometry/rotations/theory/as2reflections/index.htm&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I add images whenever I can, and I often link back to the source materials where I learned the topic, in case I want to revisit. I also tie the flashcard-making habit with my note-taking habit. For example, the above card example is directly the result of the note on &lt;a href=&quot;https://notes.lesleylai.info/Concepts/two-reflections-give-a-rotation#intuition&quot; target=&quot;_blank&quot;&gt;two reflections give a rotation&lt;span&gt;&lt;/span&gt;&lt;/a&gt; in my digital garden.&lt;/p&gt;
&lt;p&gt;Spaced repetition is not just for memorization; it can probably be viewed as a scheduled, recurrent task. So I put in things that people might not consider appropriate for flashcards. For example, I have a deck for math problems that I did wrong in the past. I use this basically to schedule practices. I put them into a separate Anki deck because I can only practice math with pen and paper, and definitely cannot do it outside.&lt;/p&gt;
&lt;p&gt;The “recurrent tasks” perspective also gives me another insight: each card is a burden, so don’t be afraid to delete cards you don’t need. I generally spend around 1 to 30 minutes reviewing old Anki cards per day, depending on how many cards I added in previous days. I want to keep it as lightweight and low-overhead as possible, and that’s the only way I can keep this habit.&lt;/p&gt;
&lt;p&gt;Nevertheless, the little time spent reviewing cards (and much more time writing them) is already worthwhile. I often pick up learning projects like a book and an &lt;a href=&quot;/en/moocs/&quot;&gt;online course&lt;/a&gt;, get busy with life, and pause them for a year. I used to forget everything. Now, after a year, I can still just pick up where I left off. How cool is that?&lt;/p&gt;
&lt;p&gt;Is this all just illusion and confirmation bias? I don’t know. People are notoriously bad at judging their own learning and productivity. While there is an abundance of evidence on spaced repetition, the empirical evidence on Anki specifically is thin and drawn mostly from studies of medical students rather than from STEM fields. However, we make decisions with imperfect knowledge all the time. For me, this one has been worth it.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#resources&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://borretti.me/article/effective-spaced-repetition&quot; target=&quot;_blank&quot;&gt;Effective Spaced Repetition&lt;span&gt;&lt;/span&gt;&lt;/a&gt; - Give a lot concrete examples on how to make flashcards. This was one article I read to get started&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Opinion</category><category>Learning</category></item><item><title>Fifty Shades of OOP</title><link>https://lesleylai.info/en/fifty_shades_of_oop</link><guid isPermaLink="true">https://lesleylai.info/en/fifty_shades_of_oop</guid><description>This post talks about the many different aspects under the umbrella term OOP</description><pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;OOP-bashing seems fashionable nowadays. I decided to write this article after seeing two OOP-related articles on &lt;a href=&quot;https://lobste.rs/&quot; target=&quot;_blank&quot;&gt;Lobsters&lt;span&gt;&lt;/span&gt;&lt;/a&gt; in quick succession. I’m not interested in defending or attacking OOP, but I do want to throw in my two cents and offer a more nuanced view.&lt;/p&gt;
&lt;p&gt;The industry and the academy have used the term “object-oriented” to mean so many different things. One thing that makes conversations around OOP so unproductive is the lack of consensus on what OOP is.&lt;/p&gt;
&lt;p&gt;What is Object-Oriented Programming? &lt;a href=&quot;https://en.wikipedia.org/wiki/Object-oriented_programming&quot; target=&quot;_blank&quot;&gt;Wikipedia defines it&lt;span&gt;&lt;/span&gt;&lt;/a&gt; as “a programming paradigm based on the concept of objects.” This definition is unsatisfactory, as it requires a definition of an “object” and fails to encompass the disparate ways the term is used in the industry. There is also &lt;a href=&quot;https://www.purl.org/stefan_ram/pub/doc_kay_oop_en&quot; target=&quot;_blank&quot;&gt;Alan Kay’s vision of OOP&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. However, the way most people use the term has drifted apart, and I don’t want to fall into &lt;a href=&quot;https://en.wikipedia.org/wiki/Essentialism&quot; target=&quot;_blank&quot;&gt;essentialism&lt;span&gt;&lt;/span&gt;&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Etymological_fallacy&quot; target=&quot;_blank&quot;&gt;etymological fallacy&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by insisting on a “true” meaning.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;It’s funny that after this post got published, some comments on it were arguing the definitive definition of objects with very different criteria, such as (i) Alan Kay &amp;amp; message passing, (ii) anything provides encapsulation (including closures and modules), (iii) dynamic dispatch. (iv) methods.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Instead, I think it is better to treat OOP as a mixed bag of interrelated ideas and examine them individually. Below, I will survey some ideas related to OOP and mention their pros and cons (in my subjective mind).&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#classes&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Classes&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Object-oriented programming is a method of implementation in which programs are organized as cooperative collections of objects, each of which represents an instance of some class, and whose classes are all members of a hierarchy of classes united via inheritance relationships. — Grady Booch&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Classes extend the idea of a “struct” or “record” with support for the method syntax, information hiding, and inheritance. We will talk about those specific features later.&lt;/p&gt;
&lt;p&gt;Classes can also be viewed as blueprints for objects. It is not the only way to do that, and &lt;em&gt;prototypes&lt;/em&gt; is an alternative pioneered by &lt;a href=&quot;https://en.wikipedia.org/wiki/Self_(programming_language)&quot; target=&quot;_blank&quot;&gt;Self&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and, most famously, used by JavaScript. Personally, I feel that prototypes are harder to wrap one’s head around compared to classes. Even JavaScript tries to hide its usage of prototypes from newcomers with ES6 classes.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;When I learned JavaScript, prototype inheritance and the semantics of &lt;code&gt;this&lt;/code&gt; were two of the topics I struggled with the most.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2&gt;&lt;a href=&quot;#method-syntax&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Method Syntax&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;In Japanese, we have sentence chaining, which is similar to method chaining in Ruby — &lt;a href=&quot;https://evrone.com/blog/yukihiro-matsumoto-interview&quot; target=&quot;_blank&quot;&gt;Yukihiro Matsumoto&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The method syntax is one of the less controversial OOP features. It captures common programming use cases involving operations on a specific subject. Even in languages without methods, it is common to see functions effectively serve as methods by taking the relevant data as their first argument (or last, in languages with currying).&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;We will revisit the idea of “operations on a specific subject” (essentially bundle data and behavior) when talking about &lt;a href=&quot;#encapsulation&quot;&gt;encapsulation&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The syntax involves method definitions and method calls. Usually, languages supporting methods have both, unless you consider the “pipe operators” in functional languages as a form of method call.&lt;/p&gt;
&lt;p&gt;The method call syntax aids IDE autocompletion, and method chaining is often more ergonomic than nested function calls (similar to the pipe operator in functional languages).&lt;/p&gt;
&lt;p&gt;There are some debatable aspects of the method syntax, too. First, in many languages, methods are often not definable outside of a class, which causes a power imbalance compared to functions. There are certain exceptions, such as Rust (methods are always defined outside of the struct), Scala, Kotlin, and C# (extension methods).&lt;/p&gt;
&lt;p&gt;Second, in many languages, &lt;code&gt;this&lt;/code&gt; or &lt;code&gt;self&lt;/code&gt; is implicit. This keeps the code more concise, but it can also introduce confusion and increase the risk of accidental name shadowing. Another drawback of an implicit this is that it is always passed as a pointer, and its type cannot be changed. This means you cannot pass it as a copy, and sometimes this indirection leads to performance issues. More importantly, because the type of this is fixed, you cannot write generic functions that accept different &lt;code&gt;this&lt;/code&gt; types. Python and Rust got &lt;em&gt;this&lt;/em&gt; right from the start, and C++ just fixed this issue in C++23 with &lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html&quot; target=&quot;_blank&quot;&gt;deducing this&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Third, in languages with both “free functions” and methods, they become two incompatible ways to do the same thing. This can cause problems in generic code. Rust addresses this issue by &lt;a href=&quot;https://doc.rust-lang.org/stable/reference/expressions/call-expr.html#disambiguating-function-calls&quot; target=&quot;_blank&quot;&gt;allowing fully qualifying a method name and treating it as a function&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fourth, the dot notation is used for both instance variable accesses and method calls in most languages. This is an intentional choice to make methods look more &lt;a href=&quot;https://en.wikipedia.org/wiki/Uniform_access_principle&quot; target=&quot;_blank&quot;&gt;uniform&lt;span&gt;&lt;/span&gt;&lt;/a&gt; with objects. In certain dynamically typed languages where &lt;em&gt;methods are instance variables&lt;/em&gt;, this is fine and pretty much not even a choice. On the other hand, in languages like C++ or Java, this can cause confusion and shadowing problems.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#information-hiding&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Information Hiding&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Its interface or definition was chosen to reveal as little as possible about its inner workings — &lt;a href=&quot;https://dl.acm.org/doi/10.1145/361598.361623&quot; target=&quot;_blank&quot;&gt;[Parnas, 1972b]&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In Smalltalk, all instance variables are not directly accessible from outside the object, and all methods are exposed. More modern OOP languages support information hiding via access specifiers like &lt;code&gt;private&lt;/code&gt; at the class level. Even non-OOP languages usually support information hiding in some way, be it module systems, opaque types, or even C’s header separation.&lt;/p&gt;
&lt;p&gt;Information hiding is a good way to prevent &lt;a href=&quot;https://en.wikipedia.org/wiki/Class_invariant&quot; target=&quot;_blank&quot;&gt;invariant&lt;span&gt;&lt;/span&gt;&lt;/a&gt; from being violated. It is also a good way to separate frequently changed implementation details from a stable interface.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Unfortunately, I’ve seen too many university courses teach &lt;code&gt;private&lt;/code&gt; and ritualistic getters/setters without mentioning the rationale.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Nevertheless, aggressively hiding information may cause unnecessary boilerplate or &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstraction_inversion&quot; target=&quot;_blank&quot;&gt;abstraction inversion&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Another criticism comes from functional programmers, who argue that you don’t need to maintain invariants and thus don’t need much information hiding if data is &lt;em&gt;immutable&lt;/em&gt;. And, in a sense, OOP encourages people to write mutable objects that must be maintained as invariants.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;In languages that don’t support immutable data well, hiding data and only exposing getters is a way to make an object immutable, though.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Information hiding also encourages people to create small, self-contained objects that “know how to handle themselves,” which leads directly into the topic of encapsulation.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#encapsulation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Encapsulation&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;If you can, just move all of that behavior into the class it helps. After all, OOP is about letting objects take care of themselves. — Bob Nystrom, &lt;a href=&quot;https://gameprogrammingpatterns.com/singleton.html&quot; target=&quot;_blank&quot;&gt;Game Programming Patterns&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Encapsulation is often confused with information hiding, but the two are distinct. Encapsulation refers to bundling data with the functions that operate on it. OOP languages directly support encapsulation with objects/classes and the method syntax, but there are other approaches. Many modern languages also support &lt;a href=&quot;https://en.wikipedia.org/wiki/Closure&quot; target=&quot;_blank&quot;&gt;closures&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (in fact, closures and objects can simulate each other). There are also other lesser-known approaches, such as &lt;a href=&quot;https://ocaml.org/docs/modules&quot; target=&quot;_blank&quot;&gt;the module system&lt;span&gt;&lt;/span&gt;&lt;/a&gt; found in the ML family.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Data-oriented_design&quot; target=&quot;_blank&quot;&gt;Data-oriented design&lt;span&gt;&lt;/span&gt;&lt;/a&gt; has a lot to say about bundling data and functionality. When many objects exist, it is often much more efficient to process them in batches rather than individually. Having small objects with distinct behaviors can lead to poor data locality, more indirection, and fewer opportunities for parallelism. Of course, advocates of data-oriented design don’t reject encapsulation outright, but they encourage a more coarse-grained form of it, &lt;a href=&quot;https://youtu.be/wo84LFzx5nI?si=ONwbHrfi0XVdSh3U&quot; target=&quot;_blank&quot;&gt;organized around how the code is actually used rather than how the domain model is conceptually structured&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#interfaces&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Interfaces&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“No part of a complex system should depend on the internal details of any other part.” — Daniel, Ingalls. “&lt;a href=&quot;https://wiki.squeak.org/squeak/uploads/400/Smalltalk-76.pdf&quot; target=&quot;_blank&quot;&gt;The Smalltalk-76 Programming System Design and Implementation&lt;span&gt;&lt;/span&gt;&lt;/a&gt;”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Separation of interface and implementation is an old idea closely related to information hiding, encapsulation, and &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_data_type&quot; target=&quot;_blank&quot;&gt;abstract data type&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. In some sense, even C’s header files can be considered an interface, but OOP usage of “interface” most often refers to a specific set of language constructs that support polymorphism (typically implemented via inheritance). Usually, an interface can’t contain data, and in more restricted languages (e.g., early versions of Java), they can’t contain method implementations either. The same idea of an interface is also common in non-OOP languages: Haskell type classes, Rust traits, and Go interfaces all serve the role of specifying an abstract set of operations independent of implementations.&lt;/p&gt;
&lt;p&gt;Interface is often considered a simpler, more disciplined alternative to full-blown class inheritance. It is a single-purpose feature and doesn’t suffer from the same diamond problem that plagues multiple inheritance.&lt;/p&gt;
&lt;p&gt;Interface is also extremely useful in combination with &lt;a href=&quot;https://en.wikipedia.org/wiki/Parametric_polymorphism&quot; target=&quot;_blank&quot;&gt;parametric polymorphism&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, since it allows you to constrain the operations a type parameter must support. Dynamically-typed languages (and C++/D template) achieve something similar through &lt;a href=&quot;https://en.wikipedia.org/wiki/Duck_typing&quot; target=&quot;_blank&quot;&gt;duck-typing&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but even languages with duck-typing introduce interface constructs later to express constraints more explicitly (e.g., C++ concepts or TypeScript interfaces).&lt;/p&gt;
&lt;p&gt;The interface as implemented in OOP languages often has a runtime cost, but that’s not always the case. For example, &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints.html&quot; target=&quot;_blank&quot;&gt;C++ concepts&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an example that only supports compile-time, and Rust’s trait only has opt-in runtime polymorphism support via &lt;code&gt;dyn&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#late-binding&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Late Binding&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things — &lt;a href=&quot;https://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en&quot; target=&quot;_blank&quot;&gt;Alan Kay&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Late binding refers to delaying the lookup of a method or a member until runtime. It is the default of most dynamic-typed languages, where method calls are often implemented as a hash table lookup, but can also be achieved with other means, such as dynamic loading or function pointers.&lt;/p&gt;
&lt;p&gt;A key aspect of late binding is that behaviour can be changed while the software is still running, enabling all kinds of hot-reloading and monkey-patching workflows.&lt;/p&gt;
&lt;p&gt;Consider the following Python program:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bar&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; foo() &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(bar()) &lt;/span&gt;&lt;span&gt;# 43&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(bar()) &lt;/span&gt;&lt;span&gt;# 101&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;foo&lt;/code&gt; is not defined when &lt;code&gt;bar&lt;/code&gt; is defined. The name lookup for &lt;code&gt;foo&lt;/code&gt; happens when &lt;code&gt;bar&lt;/code&gt; is called. The first call to &lt;code&gt;bar&lt;/code&gt; is already interesting, though the same effect can still be achieved in other languages via constructs that makes functions mutually recursive (e.g. forward declaration or &lt;code&gt;letrec&lt;/code&gt;).&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Remember the fact that late-binding naturally supports mutually-recursive function calls. We will talk about it in &lt;a href=&quot;#open-recursion&quot;&gt;open recursion&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The more crucial point is the second part of the example. Before the second call to &lt;code&gt;bar&lt;/code&gt;, we changed &lt;code&gt;foo&lt;/code&gt;’s implementation, and the call to &lt;code&gt;bar&lt;/code&gt; automatically reflects that. This is not something achievable without late binding.&lt;/p&gt;
&lt;p&gt;The downside of late binding is its non-trivial performance cost. Moreover, it can also be a footgun for breaking invariants or even interface mismatches. Its mutable nature can also introduce subtler issues, for example, the “late binding closures” pitfall in Python.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#dynamic-dispatch&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Dynamic Dispatch&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A programming paradigm in C++ using Polymorphism based on runtime function dispatch using virtual functions — &lt;a href=&quot;https://youtu.be/32tDTD9UJCE?si=OqBHJ3PecCEvidoL&quot; target=&quot;_blank&quot;&gt;Back to Basics: Object-Oriented Programming - Jon Kalb - CppCon 2019&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A concept related to late binding is dynamic dispatch, in which the implementation of a polymorphic operation is selected at runtime. The two concepts overlap, though dynamic dispatch focuses more on selecting multiple known polymorphic operations rather than on name lookup.&lt;/p&gt;
&lt;p&gt;In a dynamically typed language, dynamic dispatch is the default since everything is late-bound. In statically typed languages, it is usually implemented as a virtual function table that looks something like this under the hood:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VTable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// function pointer to destroy the base&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&lt;span&gt; (*&lt;/span&gt;&lt;span&gt;destroy&lt;/span&gt;&lt;span&gt;)(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;BaseClass&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// function pointer to one method implementation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&lt;span&gt; (*&lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span&gt;)();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// function pointer to another method implementation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; (*&lt;/span&gt;&lt;span&gt;bar&lt;/span&gt;&lt;span&gt;)(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BaseClass&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VTable&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; vtable;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;These languages also provide compile-time guarantees that the vtable contains valid operations for the type.&lt;/p&gt;
&lt;p&gt;Dynamic dispatch can be decoupled from inheritance, whether by manually implementing a v-table (e.g., C++‘s “type-erased types” such as &lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/functional/function&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;std::function&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;) or an interface/trait/typeclass kind of constructs. When not paired with inheritance, dynamic dispatch alone is usually not considered “OOP.”&lt;/p&gt;
&lt;p&gt;Another thing to note is that the pointer to the v-table can be directly inside the object (e.g., C++) or embedded in “fat pointers” (e.g., Go and Rust).&lt;/p&gt;
&lt;p&gt;Complaints about dynamic dispatch are usually about its performance. Although a virtual function call itself can be pretty fast, it &lt;a href=&quot;https://johnnysswlab.com/the-true-price-of-virtual-functions-in-c/&quot; target=&quot;_blank&quot;&gt;opens room for missing compiler inlining opportunities, cache misses, and branch mispredictions&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#inheritance&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Inheritance&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;programming using class hierarchies and virtual functions to allow manipulation of objects of a variety of types through well-defined interfaces and to allow a program to be extended incrementally through derivation — &lt;a href=&quot;https://www.stroustrup.com/bs_faq.html#oop&quot; target=&quot;_blank&quot;&gt;Bjarne Stroustrup&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Inheritance has a long history, way backed to &lt;a href=&quot;https://en.wikipedia.org/wiki/Simula&quot; target=&quot;_blank&quot;&gt;Simula 67&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. It is probably the most iconic feature of OOP. Almost every language marketed as “object-oriented” includes it, while languages that avoid OOP typically omit it.&lt;/p&gt;
&lt;p&gt;It can be damn &lt;em&gt;convenient&lt;/em&gt;. In many cases, using an alternative approach will result in significantly more boilerplate.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;My shameful confession is that I sometimes miss inheritance when coding Rust.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;On the other hand, inheritance is a very &lt;a href=&quot;https://en.wikipedia.org/wiki/Orthogonality_(programming)&quot; target=&quot;_blank&quot;&gt;non-orthogonal&lt;span&gt;&lt;/span&gt;&lt;/a&gt; feature. It is a single mechanism that enables dynamic dispatch, subtyping polymorphism, interface/implementation segregation, and code reuse. It is flexible, though that flexibility makes it easy to misuse. For that reason, some languages nowadays replace it with more restrictive alternative constructs.&lt;/p&gt;
&lt;p&gt;There are some other problems with inheritance. First, using inheritance almost certainly means you are paying the performance cost of dynamic dispatch and heap allocation. In some languages, such as C++, you can use inheritance without dynamic dispatch and heap allocation, and there are some valid use cases (e.g., code reuse with &lt;a href=&quot;https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern&quot; target=&quot;_blank&quot;&gt;CRTP&lt;span&gt;&lt;/span&gt;&lt;/a&gt;), but the majority of uses of inheritance are for runtime polymorphism (and thus rely on dynamic dispatch).&lt;/p&gt;
&lt;p&gt;Second, inheritance implements subtyping in an unsound way, requiring programmers to manually enforce the &lt;a href=&quot;https://en.wikipedia.org/wiki/Liskov_substitution_principle&quot; target=&quot;_blank&quot;&gt;Liskov substitution principle&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, inheritance hierarchies are rigid. They suffer from issues like the diagonal problem, and that inflexibility is one of the main reasons people prefer composition over inheritance. The &lt;a href=&quot;https://gameprogrammingpatterns.com/component.html&quot; target=&quot;_blank&quot;&gt;component pattern chapter of Game Programming Patterns&lt;span&gt;&lt;/span&gt;&lt;/a&gt; provides a good example.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#subtyping-polymorphism&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Subtyping Polymorphism&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;If for each object  of type  there is another object  of type  such that for all programs  defined in terms of , the behavior of  is unchanged when  is substituted for , then  is a subtype of . — Barbara Liskov, “&lt;a href=&quot;https://www.cs.tufts.edu/~nr/cs257/archive/barbara-liskov/data-abstraction-and-hierarchy.pdf&quot; target=&quot;_blank&quot;&gt;Data Abstraction and Hierarchy&lt;span&gt;&lt;/span&gt;&lt;/a&gt;”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Subtyping describes an “is a” relation between two types. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Liskov_substitution_principle&quot; target=&quot;_blank&quot;&gt;Liskov substitution principle&lt;span&gt;&lt;/span&gt;&lt;/a&gt; defines the property that safe subtyping relationships must uphold.&lt;/p&gt;
&lt;p&gt;OOP languages often support subtyping via inheritance, but note that inheritance doesn’t always model subtyping, and it is not the only form of subtyping either. Various interface/trait constructs in non-OOP languages often support subtyping. And besides &lt;em&gt;nominal subtyping&lt;/em&gt;, where one explicitly declares the subtyping relationship, there are also &lt;em&gt;structural subtyping&lt;/em&gt;, where the subtyping is implicit if one type contains all the features of another type. Good examples of structural subtyping include OCaml (&lt;a href=&quot;https://dev.realworldocaml.org/objects.html&quot; target=&quot;_blank&quot;&gt;objects&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and polymorphic variants) and TypeScript interfaces. Subtyping also shows in all kinds of little places, such as Rust lifetime and TypeScript’s coercion from a non-nullable type to its nullable counterpart.&lt;/p&gt;
&lt;p&gt;A related concept to subtyping is &lt;a href=&quot;https://en.wikipedia.org/wiki/Type_variance&quot; target=&quot;_blank&quot;&gt;variance&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (not related to class-invariant), which bridges parametric polymorphism and subtyping. I won’t bother explaining variance here, as this topic probably needs an entire blog post to explain well. It is a great ergonomic boost (e.g., C++ pointers will be unusable for polymorphic use if they are not covariant), but most languages only implement a limited, hard-coded version, because it is hard to understand and also error-prone. In particular, mutable data types should usually be invariant, and Java/C#‘s covariant arrays are a primary example on this gone wrong. Only a few languages allow programmers to explicitly control variance, including &lt;a href=&quot;https://docs.scala-lang.org/tour/variances.html&quot; target=&quot;_blank&quot;&gt;Scala&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://kotlinlang.org/docs/generics.html&quot; target=&quot;_blank&quot;&gt;Kotlin&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Type conversion via subtyping relationships is often implicit. Implicit conversion has a bad reputation. Though doing it with subtyping is ergonomic, and is probably the least surprising kind of implicit conversion. Another way to view subtyping is as the dual of implicit conversions. We can “fake” a subtyping relation with implicit conversion. For example, C++ templated types are invariant, but &lt;code&gt;std::unique_ptr&lt;/code&gt; achieves covariance with an implicit conversion from &lt;code&gt;std::unique_ptr&amp;lt;Derived&amp;gt;&lt;/code&gt; to &lt;code&gt;std::unique_ptr&amp;lt;Base&amp;gt;&lt;/code&gt;. &lt;a href=&quot;https://journal.stuffwithstuff.com/2023/10/19/does-go-have-subtyping/&quot; target=&quot;_blank&quot;&gt;Does Go Have Subtyping?&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is a good article to further explore this idea.&lt;/p&gt;
&lt;p&gt;One reason that language designers often try to avoid subtyping is the implementation complexity. Integrating bidirectional type inference and subtyping is notoriously difficult. Stephen Dolan’s 2016 thesis &lt;a href=&quot;https://www.cs.tufts.edu/~nr/cs257/archive/stephen-dolan/thesis.pdf&quot; target=&quot;_blank&quot;&gt;Algebraic Subtyping&lt;span&gt;&lt;/span&gt;&lt;/a&gt; makes good progress addressing this issue.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#message-passing&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Message Passing&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages — &lt;a href=&quot;https://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en&quot; target=&quot;_blank&quot;&gt;Alan Kay&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Message passing means using objects that send each other “messages” as a way of execution. It is the centric theme of Alan Kay’s vision of OOP, though the definition can be pretty vague. An important point is that message names are late-bound, and the structures of these messages are not necessarily fixed at compile time.&lt;/p&gt;
&lt;p&gt;Many early object-oriented concepts were influenced by distributed and simulation systems, where message passing is natural. However, in the era where most people work on single-threaded code, the message was gradually forgotten in languages such as C++ and Java. The method syntax only has limited benefit compared to the original message-passing idea (Bjarne Stroustrup was definitely aware of the idea from Simula, but there is practical constraint on how to make it fast). There was still some genuine message passing, but only in specific areas such as inter-process communication or highly event-driven systems.&lt;/p&gt;
&lt;p&gt;Message passing gains a Renaissance in concurrent programming, ironically through non-OOP languages like Erlang and Golang, with constructs such as actors and channels. This kind of &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared-nothing_architecture&quot; target=&quot;_blank&quot;&gt;shared-nothing concurrency&lt;span&gt;&lt;/span&gt;&lt;/a&gt; removed a whole range of data race and race condition bugs. In combination with supervision, actors also provide fault tolerance, so that the failure of one actor will not affect the entire program.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#open-recursion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Open Recursion&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;In general, a rule of thumb is: use classes and objects in situations where open recursion is a big win. — &lt;a href=&quot;https://dev.realworldocaml.org/objects.html&quot; target=&quot;_blank&quot;&gt;Real World OCaml&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Originating in the famous &lt;a href=&quot;https://www.cis.upenn.edu/~bcpierce/tapl/&quot; target=&quot;_blank&quot;&gt;Types and Programming Languages&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, &lt;em&gt;open recursion&lt;/em&gt; is probably the least well-known and understood term in this blog post. Nevertheless, it just describes a familiar property of object-oriented systems: methods for an object can call each other, even if they are defined in different classes in the inheritance hierarchy.&lt;/p&gt;
&lt;p&gt;The term is somewhat misleading, as there may not be recursive function calls, but here “recursion” means “mutually recursive.” The word “open” refers to “open to extension,” typically empowered by inheritance.&lt;/p&gt;
&lt;p&gt;It’s easiest to see with an example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Animal&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;print_name&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Note that we call `name` here, although it is not defined in Animal&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;{}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Cat&lt;/span&gt;&lt;span&gt;: Animal {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Kitty&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Cat cat;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// note we call print_name here, although it is not defined in Cat&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;print_name&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;I original wrote this example in Python. Though after finding Python’s late-binding semantics don’t let me further illustrate my point, I changed it to C++.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;For anyone with some familiarity with OOP, we probably take open recursion for granted, even though we may not be aware of its name. However, not all language constructs have this property. For example, in many languages, functions are not mutually recursive by default:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// This won&apos;t compile in C++ because `name` is not defined&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;print_name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Animal&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;animal&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;{}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(animal));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Cat&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Kitty&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now, in languages with late-bound functions, functions in the same module can always call each other (e.g., Python, JavaScript). There are other languages where functions are mutually recursive by default (e.g., Rust), or have forward declarations (C) or a &lt;code&gt;letrec&lt;/code&gt; construct (Scheme and ML family) to make functions mutually recursive. This solves the “recursion” part, but still not the “open” part yet:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Cat&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;print_name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Animal&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;animal&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// This still won&apos;t compile because we can&apos;t downcast an Animal to a Cat&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;{}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(animal));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Cat&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Kitty&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Let’s fix this problem by using a callback:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Animal&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::function&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; get_name;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;print_name&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;{}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;get_name&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Animal&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;make_cat&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; Animal {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.get_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []() { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Kitty&quot;&lt;/span&gt;&lt;span&gt;; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Animal cat &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;make_cat&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;print_name&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Tada, we just reinvented prototype-style dispatch!&lt;/p&gt;
&lt;p&gt;Anyway, with my quick example above, I want to show that open recursion is a property that OOP gives for free, but reproducing it in languages without built-in support can be tricky. Open recursion allows interdependent parts of an object to be defined separately, and this property is used in many instances, for example, the entire idea of &lt;a href=&quot;https://en.wikipedia.org/wiki/Decorator_pattern&quot; target=&quot;_blank&quot;&gt;decorator pattern&lt;span&gt;&lt;/span&gt;&lt;/a&gt; depends on open recursion.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#oop-best-practices&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;OOP Best Practices&lt;/h2&gt;
&lt;p&gt;Perhaps the more common complaints about OOP are not about specific language features, but rather about the programming styles it encourages. Many practices are taught as universal best practices, sometimes with rationales, but their downsides are often omitted. Some examples popped into my mind are&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Practice&lt;/th&gt;&lt;th&gt;Advantages&lt;/th&gt;&lt;th&gt;Disadvantage&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;preferring polymorphism over tagged union/if/switch/pattern matching&lt;/td&gt;&lt;td&gt;Open to extension, easier to add new cases.&lt;/td&gt;&lt;td&gt;Performance hit; Related behaviors get scattered in multiple places; harder to see the whole controll flow in one place; the &lt;a href=&quot;https://en.wikipedia.org/wiki/Expression_problem&quot; target=&quot;_blank&quot;&gt;expression problem&lt;span&gt;&lt;/span&gt;&lt;/a&gt; means adding new behavior becomes more difficult&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;making all data members private&lt;/td&gt;&lt;td&gt;Protect class invariants&lt;/td&gt;&lt;td&gt;More boilerplates; Often unnecessary to hide data without invariants; Getter/setter pairs work less well compared to direct access in languages without property syntax&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;preferring small “self-managed” objects over central “managers”&lt;/td&gt;&lt;td&gt;Harder to violate invariants, cleaner code organization&lt;/td&gt;&lt;td&gt;Potential bad data locality, missing parallelism opportunities, and duplicated references to common data (“back pointer”)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle&quot; target=&quot;_blank&quot;&gt;preferring extension rather than modification&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Prevent new features from breaking the old one. Prevent API break&lt;/td&gt;&lt;td&gt;No reason to “close” a non-public module where you own its usage. Leads to unnecessary complexity and inheritance chain; poorly designed interfaces are not changed; Can cause abstraction inversion&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;preferring abstraction over concrete implementations&lt;/td&gt;&lt;td&gt;Making more system swappable and testable&lt;/td&gt;&lt;td&gt;Overuse sacrifices readability and debuggability. Performance cost of extra indirection&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;This blog post is long enough, so I will not go into more details. Feel free to disagree with my “advantages and disadvantages”. What I want to convey is that almost all those practices come with trade-offs.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#in-the-end&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;In the End&lt;/h2&gt;
&lt;p&gt;Congratulations on making it to the end of this article! There are other topics I’d love to discuss, such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot; target=&quot;_blank&quot;&gt;RAII&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and design patterns. However, this article is long enough, so I will leave those for you to explore on your own.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://lobste.rs/s/fjf1eh/fifty_shades_oop&quot; target=&quot;_blank&quot;&gt;See discussion on Lobsters&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category>Coding</category><category>OOP</category><category>Opinion</category><category>PLT</category></item><item><title>Self hosting comments with Comentario</title><link>https://lesleylai.info/en/self-host-comentario</link><guid isPermaLink="true">https://lesleylai.info/en/self-host-comentario</guid><description>A walkthrough of how I migrated my blog&apos;s comment system from the Commento cloud service to self-hosting with Comentario, Commento&apos;s active fork. I share my experience setting up Comentario with Docker, configuring a reverse proxy with Caddy, and customizing its client-side CSS. This post also includes reflections on the learning curve of self-hosting and notes on future plans to move away from other cloud services.</description><pubDate>Fri, 25 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Edit 2026-03-12&lt;/strong&gt;: I just learned about some &lt;a href=&quot;https://notes.lesleylai.info/Concepts/Docker-will-edit-host-based-firewall-rules&quot; target=&quot;_blank&quot;&gt;nasty security gotcha&lt;span&gt;&lt;/span&gt;&lt;/a&gt; of Docker, so I changed the docker-compose snippet in this post.&lt;/p&gt;
&lt;p&gt;One of the challenges of running a static-site blog is enabling comments. This blog initially used Disqus, but I migrated to &lt;a href=&quot;https://commento.io/&quot; target=&quot;_blank&quot;&gt;Commento&lt;span&gt;&lt;/span&gt;&lt;/a&gt; since Disqus served way too much ads and tracking. Compare to alternatives, Commento also had the set of features I want from a comment system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support comments without login, but also OAuth&lt;/li&gt;
&lt;li&gt;Moderation dashboard&lt;/li&gt;
&lt;li&gt;Threaded replies&lt;/li&gt;
&lt;li&gt;Email notification&lt;/li&gt;
&lt;li&gt;Custom user avatars&lt;/li&gt;
&lt;li&gt;Markdown&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;
&lt;p&gt;It’s easy to overlook how much advertising and tracking Disqus includes when you always use ad-blockers, but even their bloated script alone is something I definitely don’t want on my website.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;For years, I used the cloud-hosted version of &lt;a href=&quot;https://commento.io/&quot; target=&quot;_blank&quot;&gt;Commento&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. However, Commento had been unmaintained for a long time, and the $99 annual fee always feels too expensive. I’d been wanting to switch to something else for a while but never quite had the motivation. That changed this year when the cloud service start to fail sporadically, and I even thought I had lost all the past comments. I also happened to be &lt;a href=&quot;/en/site-update-2025&quot;&gt;redesigning my website&lt;/a&gt; around the same time, so it felt like a natural moment to make the switch.&lt;/p&gt;
&lt;p&gt;Compare to years ago, nowadays there are much more options for comments, but I settled with &lt;a href=&quot;https://comentario.app&quot; target=&quot;_blank&quot;&gt;Comentario&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, a fork of Commento, as it is easy to migrate and has all the features that I already used. The only issue is that Comentario only supports self-hosting, which is something I don’t have experience with.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#self-hosting-setup&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Self-Hosting Setup&lt;/h2&gt;
&lt;p&gt;I am a self-hosting noob, who dreaded it so much that I even chosed a $99 annual solution a few years ago. Along the way to setting this thing up, I definitely learned a few things.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;It’s not quite accurate to say I’m a complete noob. A long time ago, I self-hosted a &lt;a href=&quot;https://www.mediawiki.org/wiki/MediaWiki&quot; target=&quot;_blank&quot;&gt;MediaWiki&lt;span&gt;&lt;/span&gt;&lt;/a&gt; instance for my math and science notes on a DigitalOcean Droplet. I vaguely remember something called “&lt;a href=&quot;https://httpd.apache.org/&quot; target=&quot;_blank&quot;&gt;Apache&lt;span&gt;&lt;/span&gt;&lt;/a&gt;”, and another thing called “&lt;a href=&quot;https://nginx.org/&quot; target=&quot;_blank&quot;&gt;nginx&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;I definitely didn’t know what I was doing, though, and whatever knowledge I picked up back then is now long forgotten. Eventually, I gave up, since the friction of both writing notes and maintaining the software in that workflow was too high.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;First, I picked a &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_private_server&quot; target=&quot;_blank&quot;&gt;VPS&lt;span&gt;&lt;/span&gt;&lt;/a&gt; service. There are a lot of cheap or even free options available online.&lt;/p&gt;
&lt;p&gt;Nowadays it is pretty common to use Docker to self-host, and &lt;a href=&quot;https://docs.comentario.app/en/getting-started/docker-compose/&quot; target=&quot;_blank&quot;&gt;Comentario supports Docker Compose out of the box&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Below are my docker configurations:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;docker-compose.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;services&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;postgres:17-alpine&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;POSTGRES_DB&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;comentario&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;POSTGRES_USER&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;postgres&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;postgres&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&quot;127.0.0.1:5432:5432&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;always&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;registry.gitlab.com/comentario/comentario&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;BASE_URL&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&amp;lt;redacted domain&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;SECRETS_FILE&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/secrets.yaml&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&quot;127.0.0.1:8080:80&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./secrets.yaml:/secrets.yaml:ro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;always&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;Yes, you could find the &lt;code&gt;&amp;lt;redacted domain&amp;gt;&lt;/code&gt; by reading the source code of this page. I’ll not save you this trouble just in case someone (or something) copy/paste this code snippet.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Comentario stores “secrets” in a separate file:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;secrets.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;postgres&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;:     &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;:     &lt;/span&gt;&lt;span&gt;5432&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;database&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;comentario&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;postgres&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;postgres&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;idp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;github&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;:    &lt;/span&gt;&lt;span&gt;&amp;lt;redacted&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;secret&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&amp;lt;redacted&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# plan to add other providers later&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Putting those two files in the same directory and I can start the app with &lt;code&gt;docker compose up -d&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#custom-domain-and-dns&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Custom Domain and DNS&lt;/h3&gt;
&lt;p&gt;Now I could access the app via the IP address. Since I already own a custom domain, all I need to do is to add an &lt;code&gt;A&lt;/code&gt; record to point to the VPS.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#reverse-proxy&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Reverse Proxy&lt;/h3&gt;
&lt;p&gt;Now I have a web app that I can access via IP address and the port &lt;code&gt;8080&lt;/code&gt;, but that is far from ideal. I don’t want expose the port and I also need to support HTTPS. I learned something called &lt;a href=&quot;https://en.wikipedia.org/wiki/Reverse_proxy&quot; target=&quot;_blank&quot;&gt;reverse proxy&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to handle exact this kind of situation.&lt;/p&gt;
&lt;p&gt;Initially I tried to use &lt;a href=&quot;https://nginx.org/&quot; target=&quot;_blank&quot;&gt;nginx&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but I setted with &lt;a href=&quot;https://caddyserver.com/&quot; target=&quot;_blank&quot;&gt;Caddy&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for simplicity. All I need to do was to write a &lt;a href=&quot;https://caddyserver.com/docs/caddyfile&quot; target=&quot;_blank&quot;&gt;Caddyfile&lt;span&gt;&lt;/span&gt;&lt;/a&gt; like this and start the Caddy server:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;Caddyfile&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;redacted domain name&amp;gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;reverse_proxy localhost:8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Yes, it is that simple!&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#client-side-and-css&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Client-Side and CSS&lt;/h2&gt;
&lt;p&gt;Adding comments to this blog is trivial &lt;a href=&quot;https://docs.comentario.app/en/configuration/embedding/&quot; target=&quot;_blank&quot;&gt;following the instruction&lt;span&gt;&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&amp;lt;redacted domain&amp;gt;/comentario.js&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;comentario-comments&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;comentario-comments&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Comentario includes its own CSS, but I needed to customize it extensively to match my site’s design. Rather than relying on CSS overrides, I chose to set &lt;code&gt;css-override=&quot;false&quot;&lt;/code&gt; on the &lt;code&gt;&amp;lt;comentario-comments&amp;gt;&lt;/code&gt; tag and bundled the full CSS file myself in this blog.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#final-notes&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Final Notes&lt;/h2&gt;
&lt;p&gt;During the migration, I also noticed a bunch of spam comments that were just copy-pasting my words verbatim. I’m not sure what their purpose was, but I deleted all of them.&lt;/p&gt;
&lt;p&gt;Also, now that I know how to self-host, I’m planning to cut my subscriptions to some other cloud-hosted services. RSS reader and a read-it-later tool immediately comes to my mind.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#resources&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Resources&lt;/h2&gt;
&lt;p&gt;I’ve browsed a lot of resources to set this up, here are the ones I found most useful (excluding documentation):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://damien.zone/my-comentario-self-hosting-setup/&quot; target=&quot;_blank&quot;&gt;my Comentario self-hosting setup | damien’s zone&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://boringtech.net/blog/intro-to-self-hosting-how-to-get-started-hosting-your-applications/&quot; target=&quot;_blank&quot;&gt;Intro to self-hosting: how to get started hosting your applications&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Meta</category><category>Web</category><category>Selfhosted</category></item><item><title>Site Update (April 2025)</title><link>https://lesleylai.info/en/site-update-2025</link><guid isPermaLink="true">https://lesleylai.info/en/site-update-2025</guid><description>This post talks about me completely rebuilding this website, moving from Gatsby.js to Astro due to build issues and Gatsby&apos;s decline.</description><pubDate>Mon, 21 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve done a complete rewrite of this site. My old version was made with &lt;a href=&quot;https://www.gatsbyjs.com/&quot; target=&quot;_blank&quot;&gt;Gatsby.js&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. While I liked the overall style, it had reached a point where I couldn’t even build it locally with a recent version of Node.js.&lt;/p&gt;
&lt;p&gt;Since Gatsby is pretty much abandoned, I choosed a new static-site generator &lt;a href=&quot;https://astro.build/&quot; target=&quot;_blank&quot;&gt;Astro&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;I do worry that Astro might end up like Gatsby since it is yet another VC-funded “open source” project. But so far, I’m happy with it.&lt;/p&gt;
 &lt;/aside&gt;
&lt;p&gt;Rebuilding this site was definitely a lot of work. The &lt;a href=&quot;https://web.archive.org/web/20250327200036/https://lesleylai.info/&quot; target=&quot;_blank&quot;&gt;previous version&lt;span&gt;&lt;/span&gt;&lt;/a&gt; had accumulated many small features over time, and reimplementing all those little details took quite a bit of effort. And while the design of this site is similar to the previous one, I still made extensive change to its layout and style. I also added some new things, such as the grid layout of the &lt;a href=&quot;/en/projects&quot;&gt;project&lt;/a&gt; page and a theme toggle.&lt;/p&gt;
&lt;p&gt;There are still two major things I need to take care of. First, I don’t have comments set up yet. I previously used the cloud-hosted version of &lt;a href=&quot;https://commento.io/&quot; target=&quot;_blank&quot;&gt;Commento&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but I plan to migrate to self-hosting using &lt;a href=&quot;https://comentario.app&quot; target=&quot;_blank&quot;&gt;Comentario&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Second, my notes are still a seperate website under the subdomain &lt;a href=&quot;https://notes.lesleylai.info/&quot; target=&quot;_blank&quot;&gt;notes.lesleylai.info&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Migrating them over to this site will be a significant task, but I plan to do it in the future.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2025-04-25&lt;/strong&gt;: The comment system is alive again! I write about my setup in &lt;a href=&quot;/en/self-host-comentario&quot;&gt;the following post&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Meta</category><category>Web</category></item><item><title>Representing an Abstract Syntax Tree in C++: Variants</title><link>https://lesleylai.info/en/ast-in-cpp-part-1-variant</link><guid isPermaLink="true">https://lesleylai.info/en/ast-in-cpp-part-1-variant</guid><description>This post explores various ways to implement an abstract syntax tree (AST) in C++. In particular, it focuses on representing &quot;variant&quot; structures that can hold values from a fixed set of alternatives.</description><pubDate>Mon, 22 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Exploring the representation of abstract syntax trees in C++ has been a long-standing fascination of mine. Over time, I’ve developed several interpreters/compilers in C++, each utilizing different approaches to representation. In this post, I aim to share the insights I wish I had when I start building language implementations in C++.&lt;/p&gt;
&lt;p&gt;Frankly, if I start on a programming language project today, I’d likely opt against C++ unless there is a very compelling reason. Nevertheless, I hope this knowledge I’ve amassed proves valuable to others.&lt;/p&gt;
&lt;p&gt;Before delving further, it’s worth noting that the question of “how to represent an AST” can be subdivided into two intertwined issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to represent a variant&lt;/li&gt;
&lt;li&gt;How to represent recursive data structure&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this post, we will mainly focus on the first issue.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#what-do-i-mean-by-variant&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;What Do I Mean by Variant?&lt;/h2&gt;
&lt;p&gt;Variant, also known as a sum type, tagged union, or discriminated union, is a data structure capable of containing a fixed set of alternatives. If you’re reading this, chances are you’ve used variants before. The “fixed set” perspective is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Expression_problem&quot; target=&quot;_blank&quot;&gt;limitation&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but for AST we normally care more about the ease of extending behaviors rather than adding new node types.&lt;/p&gt;
&lt;p&gt;Anyway, if there is any language with good support for language-level variants and pattern matching, I would go directly with those. But for C++, there are various alternative representations all with their tradeoffs and shortcomings.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#stdvariant&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;std::variant&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We’ll begin with std::variant, which is arguably the de facto “modern C++” solution for variants. It offers functionality and type safety, yet its ergonomics are &lt;a href=&quot;https://bitbashing.io/std-visit.html&quot; target=&quot;_blank&quot;&gt;debatable&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. It may also incur longer compile times compared to raw language solutions.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;std::variant&lt;/code&gt;, we could write something similar to the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;variant&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;unique_ptr&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Literal lit;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string ident;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;UnaryOp op;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprHandle expr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BinaryOp op;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprHandle lhs;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprHandle rhs;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprHandle cond_expr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprHandle if_expr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprHandle else_expr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Forward declaring everything is annoying, and we also probably want to put some common fields, such as the source location, into an AST node. This prompts the following adjustment:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;unique_ptr&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// all kinds of of the Expr here&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;SourceSpan span;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::variant&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;LiteralExpr, VariableExpr, UnaryExpr, BinaryExpr, IfExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; kind;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;Alternatively, you can inherit from &lt;code&gt;std::variant&lt;/code&gt;, which used to be broken in C++17 but &lt;a href=&quot;https://wg21.link/p2162r2&quot; target=&quot;_blank&quot;&gt;was fixed since C++20&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The above code looks alright, but the main ergonomics problem of the &lt;code&gt;std::variant&lt;/code&gt; is how to visit them. C++ doesn’t have pattern matching, and we are given a companion funciton called &lt;code&gt;std::visit&lt;/code&gt;, which accept a visitor as argument.&lt;/p&gt;
&lt;p&gt;One way to define this visitor is to create a dedicated class:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKindPrinter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lit&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ident&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;({} {})&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;op&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;&lt;span&gt;(ExprKindPrinter{}, &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This looks verbose and boilerplaty, and another option is to use generic lambdas and &lt;code&gt;if constexpr&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Helper to catch unreachable branches at compile time&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; always_false_v &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;([] (&lt;/span&gt;&lt;span&gt;auto&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;KindT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;decay_t&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;decltype&lt;/span&gt;&lt;span&gt;(kind)&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::is_same_v&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;KindT, LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lit&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::is_same_v&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;KindT, VariableExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ident&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::is_same_v&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;KindT, UnaryExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;({} {})&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;+&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;expr_to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::is_same_v&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;KindT, BinaryExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::is_same_v&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;KindT, IfExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;static_assert&lt;/span&gt;&lt;span&gt;(always_false_v&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;KindT&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;non-exhaustive visitor!&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}, &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I prefer this to the previous version.However, it still appears quite cumbersome with all the &lt;code&gt;decltype&lt;/code&gt;, &lt;code&gt;std::decay_t&lt;/code&gt;, and &lt;code&gt;std::is_same_v&lt;/code&gt; incantations. Also, &lt;a href=&quot;/en/auto-parameters&quot;&gt;since generic lambda is template&lt;/a&gt;, we have worse IDE auto-completion/error detection support when writing this code.&lt;/p&gt;
&lt;p&gt;Yet another option is to use the &lt;code&gt;overloaded&lt;/code&gt; helper:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;... &lt;/span&gt;&lt;span&gt;Ts&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;overloaded&lt;/span&gt;&lt;span&gt; : Ts... { &lt;/span&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ts&lt;/span&gt;&lt;span&gt;::operator()...; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With that we could write code like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(overloaded{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lit&lt;/span&gt;&lt;span&gt;); },&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ident&lt;/span&gt;&lt;span&gt;; },&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;({} {})&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;+&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;span&gt; /* ... */&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;span&gt; /* ... */&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}, &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This seems much cleaner compared to the previous solutions, but it still feels somewhat awkward compared to a language-integrated solution.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#discriminated-union&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Discriminated Union&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;std::variant&lt;/code&gt; was intended to supersede the traditional practice of discriminated unions that has been in use since the days of C. With the classic discriminated union, we typically have something along these lines:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;enum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKind&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;literal&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;unary&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;binary&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if_&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprKind kind;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;union&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;LiteralExpr literal;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VariableExpr variable;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;UnaryExpr unary;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BinaryExpr binary;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IfExpr if_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} data;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We loss type safety since &lt;code&gt;union&lt;/code&gt; access is not checked, but the upper side is that we can just use plain &lt;code&gt;switch&lt;/code&gt; instead of doing gymnastics with &lt;code&gt;std::visit&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;switch&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKind&lt;/span&gt;&lt;span&gt;::literal: &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;literal&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKind&lt;/span&gt;&lt;span&gt;::variable: &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ident&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Another major downside of raw union is that it can’t handle non-&lt;a href=&quot;https://en.cppreference.com/w/cpp/named_req/TrivialType&quot; target=&quot;_blank&quot;&gt;trivial types&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (e.g. &lt;code&gt;std::string&lt;/code&gt; or &lt;code&gt;std::unique_ptr&lt;/code&gt;). This is because the compiler has no idea which member’s destructor to call when destructing a union (similarly, copy and move will also be broken). If you require non-trivial types, you’ll have to write your own destructor for &lt;code&gt;Expr&lt;/code&gt;, which can become tedious and error-prone.&lt;/p&gt;
&lt;p&gt;If you opt to stick with trivial types, such as &lt;code&gt;std::string_view&lt;/code&gt; for strings and &lt;code&gt;Expr*&lt;/code&gt; for expression handles, you’ll need to consider resource management. A great strategy is to implement an allocation scheme like the arena allocator, where deallocation is unnecessary. This approach can provide a robust and reliable solution.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#enum-tag--inheritance&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Enum Tag + Inheritance&lt;/h2&gt;
&lt;p&gt;One problem with the “tagged union” approach is that it can waste memory, especially if if some of your nodes are significantly larger than others, as the size of &lt;code&gt;variant&lt;/code&gt; or &lt;code&gt;union&lt;/code&gt; will always be the size of its largest alternative. We can address this issue by using inheritance:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprKind kind;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Literal lit;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Utilizing this type closely resembles the previous one, with the notable difference being the necessity for down-casting:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;switch&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKind&lt;/span&gt;&lt;span&gt;::literal:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt;(expr));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKind&lt;/span&gt;&lt;span&gt;::variable:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; VariableExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;(expr).&lt;/span&gt;&lt;span&gt;ident&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The excessive amount of down-casting can be annoying, but we can mitigate this issue by writing some helper functions:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprKind kind;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as_literal_expr&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Literal lit;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;as_literal_expr&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;switch&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprKind&lt;/span&gt;&lt;span&gt;::literal:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;as_literal_expr&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I actually quite like this solution despite it violates “OOP best practices.” Though if you don’t have a &lt;code&gt;virtual&lt;/code&gt; destructor, you face a similar issue of the previous solution.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#a-virtual-function-that-returns-enum-tag&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;A Virtual Function That Returns Enum Tag&lt;/h2&gt;
&lt;p&gt;If you don’t mind adding virtual functions, it gives us back type safety and also solves the problem of supporting non-trivial types. Additionally, the enum tag field becomes redundant, eliminating the need to store it within the &lt;code&gt;Expr&lt;/code&gt;. Consequently, we can implement something akin to the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; ExprKind;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~Expr&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BinaryOpExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; NodeKind &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NodeKind&lt;/span&gt;&lt;span&gt;::BinaryOp; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With virtual functions, we can also implement checked down-casting, unlike the previous version:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as_literal&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; LiteralExpr&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as_literal&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; LiteralExpr&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Like the last one, this method still violates the “OOP best practice” of not using enum tags and inheritance together.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#inheritance-with-the-visitor-pattern-approach&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Inheritance with the Visitor Pattern Approach&lt;/h3&gt;
&lt;p&gt;Lastly, let’s look at the &lt;a href=&quot;https://en.wikipedia.org/wiki/Visitor_pattern&quot; target=&quot;_blank&quot;&gt;visitor pattern&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, the canonical OOP way to create and traverse variants. First, we need to define a visitor type:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~ExprVisitor&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then we adds an &lt;code&gt;accept&lt;/code&gt; method for &lt;code&gt;Expr&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; value;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string id;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Note that even though all the implementation of &lt;code&gt;accept&lt;/code&gt; looks identical, we need this duplicated code in each derived class of &lt;code&gt;Expr&lt;/code&gt; because we are overloading on the type of &lt;code&gt;*this&lt;/code&gt;. If you want to make this more explicitly, you can also change the name of the &lt;code&gt;visit&lt;/code&gt; methods in &lt;code&gt;ExprVisitor&lt;/code&gt; into something like &lt;code&gt;visit_literal&lt;/code&gt; and &lt;code&gt;visit_variable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With all that boilerplate, we can start to use our visitor. However, we immediately face another significant annoyance: unlike in languages such as Java, there is no way to make a &lt;code&gt;virtual&lt;/code&gt; function to return different types based on a template parameter:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// The following will not work!!!&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;typename&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As a result, we need to save the result of a visitor into another variable:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprPrinter&lt;/span&gt;&lt;span&gt; : ExprVisitor {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string result;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lit&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ident&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExprPrinter printer;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;expr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(printer);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;printer&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Another problem with visitor pattern is const-correctness. Although I believe that a mutable AST isn’t necessarily the best approach and &lt;a href=&quot;https://btmc.substack.com/p/how-to-store-types-after-semantic&quot; target=&quot;_blank&quot;&gt;there are superior alternatives&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, if you do need to mutate your AST, you need to define &lt;em&gt;yet&lt;/em&gt; another mutable visitor base class to achieve that. Also don’t forget about all those &lt;code&gt;accept&lt;/code&gt; member functions:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExprMutableVisitor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ExprMutableVisitor&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~ExprMutableVisitor&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;UnaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;BinaryExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;IfExpr&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;virtual&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprMutableVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LiteralExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; value;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprMutableVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VariableExpr&lt;/span&gt;&lt;span&gt; : Expr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string id;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ExprMutableVisitor&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;override&lt;/span&gt;&lt;span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;visit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Of all the alternatives I’ve presented so far, the visitor pattern is likely the slowest, because it performs &lt;a href=&quot;https://en.wikipedia.org/wiki/Double_dispatch&quot; target=&quot;_blank&quot;&gt;double dispatch&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (once at &lt;code&gt;visit&lt;/code&gt; and once at &lt;code&gt;accept&lt;/code&gt;) while all the other options perform a single dispatch. The boilerplate is also unwieldy. I would not recommend it if you don’t actually need double dispatch.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#uber-node-as-an-alternative-to-variant&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;”Uber node” as an alternative to variant?&lt;/h2&gt;
&lt;p&gt;It is convinient to have one single “uber node” type that is flexible enough to accomodate for all different kind of AST nodes, and this way we don’t need variants at all. For example, we may have something like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Node&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;NodeKind kind;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Node&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; children;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::span&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Token&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; tokens;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I have seen this approach used in “simple compiler” codebases such as &lt;a href=&quot;https://github.com/ktateish/9cc&quot; target=&quot;_blank&quot;&gt;9cc&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. One of the main upside of this approach is that if you write some tree/graph algorithm on &lt;code&gt;Node&lt;/code&gt;, it will automatically work for all nodes. The downside including performance and space waste. Also, this approach means it takes more effort to extract data from an AST node, and it is not clear whether a certain kind of node contains a certain field.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;All of the above methods are used in the wild. So, YMMV. Nonetheless, it’s crucial to remain conscious of the available options and the trade-offs associated with each.&lt;/p&gt;</content:encoded><category>Coding</category><category>C++</category><category>PLDev</category></item><item><title>Online Courses that I Recommend</title><link>https://lesleylai.info/en/moocs</link><guid isPermaLink="true">https://lesleylai.info/en/moocs</guid><description>In this post, I share a curated list of online courses that I found both enjoyable and insightful.</description><pubDate>Sun, 17 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My journey of learning from online courses started in 2013, and over the years I took a lot of them, abandoning even more along the way. Nevertheless, I’ve found online courses to be far more accommodating for self-study compared to traditional books.&lt;/p&gt;
&lt;p&gt;In this post, I’ve compiled a list of courses that I found memorable, enjoyable, and, in retrospect, actually convey high-quality information. While the selection is undoubtedly biased towards my personal interests, I hope you find them useful as well.&lt;/p&gt;
&lt;p&gt;Do note that some courses that I recommend below are not &lt;a href=&quot;https://en.wikipedia.org/wiki/Massive_open_online_course&quot; target=&quot;_blank&quot;&gt;MOOCs&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but instead university courses that happened to have lecture recordings, assignments, and other course material freely available from past offerings. As a result, you may need to do some extra digging to locate the course material.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#meta-learning&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Meta-Learning&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coursera.org/learn/learning-how-to-learn&quot; target=&quot;_blank&quot;&gt;Learning How to Learn&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — “Learning how to learn” is an essential skill that I find people, including myself, quite lacking. Some people may consider this one offer pretty “obvious” advice. Indeed, most actionable advice taught in this course is not new. However, I don’t think it is right to dismiss the course as “common sense,” for common senses are often contradictory with each other. This course, instead, offers scientific validation for effective learning practices.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#math&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Math&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#calculus&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Calculus&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Calculus: Single Variable by Robert Ghrist [&lt;a href=&quot;https://www.coursera.org/learn/single-variable-calculus&quot; target=&quot;_blank&quot;&gt;part 1&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] [&lt;a href=&quot;https://www.coursera.org/learn/differentiation-calculus&quot; target=&quot;_blank&quot;&gt;part 2&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] [&lt;a href=&quot;https://www.coursera.org/learn/integration-calculus&quot; target=&quot;_blank&quot;&gt;part 3&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] [&lt;a href=&quot;https://www.coursera.org/learn/applications-calculus&quot; target=&quot;_blank&quot;&gt;part 4&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] [&lt;a href=&quot;https://www.coursera.org/learn/discrete-calculus&quot; target=&quot;_blank&quot;&gt;part 5&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] — A multi parts course on single variable calculus&lt;/li&gt;
&lt;li&gt;MIT OCW &lt;a href=&quot;https://ocw.mit.edu/courses/18-02sc-multivariable-calculus-fall-2010/&quot; target=&quot;_blank&quot;&gt;Multivariable Calculus&lt;span&gt;&lt;/span&gt;&lt;/a&gt; as main course and things below as supports
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www2.math.upenn.edu/~ghrist/BLUE.html&quot; target=&quot;_blank&quot;&gt;Calculus Blue&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — Again by Professor Ghrist. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Matrix_calculus&quot; target=&quot;_blank&quot;&gt;matrix calculus&lt;span&gt;&lt;/span&gt;&lt;/a&gt; perspective is refreshing, but the pace is too fast to use as a standalone material imo&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.khanacademy.org/math/multivariable-calculus&quot; target=&quot;_blank&quot;&gt;Khan Acedemy&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#linear-algebra&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Linear algebra&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MIT OCW &lt;a href=&quot;https://ocw.mit.edu/courses/18-06sc-linear-algebra-fall-2011/&quot; target=&quot;_blank&quot;&gt;Linear Algebra&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Prof. Gilbert Strang as main course — If you spend some time doing online learning for math, it is likely you already heard the name of Prof. Strang.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab&quot; target=&quot;_blank&quot;&gt;Essense of linear algebra&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by 3Blue1Brown&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#differential-equations&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Differential Equations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MIT OCW &lt;a href=&quot;https://ocw.mit.edu/courses/18-03sc-differential-equations-fall-2011/&quot; target=&quot;_blank&quot;&gt;Differential Equations&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — My only complaint is the low resolution of the video lecture&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.khanacademy.org/math/differential-equations&quot; target=&quot;_blank&quot;&gt;Khan Academy Differential Equations&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — Accessible though very incomplete&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#discrete-math&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Discrete Math&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MIT OCW &lt;a href=&quot;https://ocw.mit.edu/courses/6-042j-mathematics-for-computer-science-spring-2015/&quot; target=&quot;_blank&quot;&gt;Mathematics for Computer Science&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#signal-processing&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Signal Processing&lt;/h3&gt;
&lt;p&gt;Wikipedia says that signal processing is an electrical engineering subfield, but in reality the same technique is used in various other fields as well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MIT OCW &lt;a href=&quot;https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/&quot; target=&quot;_blank&quot;&gt;6.003 Signals and Systems&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — I enjoy the inereactive teaching style.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#logic&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Logic&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://intrologic.stanford.edu/homepage/index.html&quot; target=&quot;_blank&quot;&gt;Stanford Introduction to Logic&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — I took a solid introductory logic course at university, but this course still introduces many new concepts or explains familiar ones from a fresh perspective.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#computer-science-and-programming&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Computer Science and Programming&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;#intro&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Intro&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stanford &lt;a href=&quot;https://web.stanford.edu/class/cs106a/&quot; target=&quot;_blank&quot;&gt;CS106A&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://web.stanford.edu/class/cs106b/&quot; target=&quot;_blank&quot;&gt;106B&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, and &lt;a href=&quot;https://learncs.me/stanford/cs106l&quot; target=&quot;_blank&quot;&gt;106L&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — These were course series that started my Computer Science Journey. The 2008 edition that I took was way too old and outdated, but there are newer versions of offering online.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#computer-graphics-and-gpu-programming&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Computer Graphics and GPU Programming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CMU &lt;a href=&quot;https://www.youtube.com/playlist?list=PL9_jI1bdZmz2emSh0UQ5iOdT2xRHFHL7E&quot; target=&quot;_blank&quot;&gt;15-462/662 Computer Graphics&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — Great intro to Computer Graphics. And even experienced folks can learn a lot here.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cis565-fall-2023.github.io/&quot; target=&quot;_blank&quot;&gt;CIS 5650 GPU Programming and Architecture&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — Project-oriented introduction of GPU programming in CUDA with a Computer Graphics flavor&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cs87-dartmouth.github.io/Fall2022/&quot; target=&quot;_blank&quot;&gt;CS 87/287 | Rendering Algorithms&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — Mainly focus on offline rendering. Unlike most courses I recommended here, this one doesn’t have lecture videos. Though following slides and doing homework are effective enough for me.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#programming-languages-and-compilers&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Programming Languages and Compilers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Programming Languages by University of Washington [&lt;a href=&quot;https://www.coursera.org/learn/programming-languages&quot; target=&quot;_blank&quot;&gt;Part A&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] [&lt;a href=&quot;https://www.coursera.org/learn/programming-languages-part-b&quot; target=&quot;_blank&quot;&gt;Part B&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] [&lt;a href=&quot;https://www.coursera.org/learn/programming-languages-part-c&quot; target=&quot;_blank&quot;&gt;Part C&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] — A three-part course on programming languages. I find the content quite shallow compared to the undergrad PL course I took at university, but it serves as a good introduction and Prof. Dan Grossman is enthusiastic about the topics.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cs.cornell.edu/courses/cs6120/2023fa/self-guided/&quot; target=&quot;_blank&quot;&gt;CS 6120: Advanced Compilers&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Cornell University — mainly talks about compiler optimization&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#system-programming&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;System Programming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CMU &lt;a href=&quot;https://www.cs.cmu.edu/~213/&quot; target=&quot;_blank&quot;&gt;15-213/15-513 Introduction to Computer Systems&lt;span&gt;&lt;/span&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;http://csapp.cs.cmu.edu/3e/labs.html&quot; target=&quot;_blank&quot;&gt;CSAPP&lt;span&gt;&lt;/span&gt;&lt;/a&gt; textbook used by this course is a classic. However, do note that there are &lt;a href=&quot;https://blog.regehr.org/archives/1393&quot; target=&quot;_blank&quot;&gt;some serious misinfo regarding C&lt;span&gt;&lt;/span&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;For years I thought signed-integer overflow has wrapping behavior in C because of this book&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nand2tetris.org/&quot; target=&quot;_blank&quot;&gt;Nand2Tetris&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — If you want a single survey course that covers logic gates, computer architecture, assembly, and OS, then this is a course for you. Of course, it covers none of the topics in-depth, but still an awesome course nonetheless.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#misc&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Misc&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://missing.csail.mit.edu/&quot; target=&quot;_blank&quot;&gt;The Missing Semester of Your CS Education&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — talks about the usage of various important tools for software engineering&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#psychology&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Psychology&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Yale &lt;a href=&quot;https://oyc.yale.edu/introduction-psychology/psyc-110&quot; target=&quot;_blank&quot;&gt;Introduction to Psychology&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — There is a &lt;a href=&quot;https://www.coursera.org/learn/introduction-psychology&quot; target=&quot;_blank&quot;&gt;new version&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by the same professor on Coursera&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#physics&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Physics&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coursera.org/learn/einstein-relativity&quot; target=&quot;_blank&quot;&gt;Understanding Einstein: The Special Theory of Relativity&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Stanford — A (very) qualitative intro to the special theory of relativity that I think is accessible even for folks without a STEM background&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#tips-on-finding-good-courses&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Tips on finding good courses&lt;/h2&gt;
&lt;p&gt;My observation is that traditional university courses (such as the ones from &lt;a href=&quot;https://ocw.mit.edu/&quot; target=&quot;_blank&quot;&gt;MIT OCW&lt;span&gt;&lt;/span&gt;&lt;/a&gt;) have higher quality on average than MOOCs. Unfortunately, most university courses lack lecture videos, which I consider indispensable. On the other hand, while lecture videos are invaluable, courses relying solely on videos—a common occurrence on YouTube—are not enough. Prefer courses with a lot of supplementary materials and homework.&lt;/p&gt;
&lt;p&gt;Among Mooc platforms, I think &lt;a href=&quot;https://www.coursera.org/&quot; target=&quot;_blank&quot;&gt;Coursera&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.edx.org/&quot; target=&quot;_blank&quot;&gt;Edx&lt;span&gt;&lt;/span&gt;&lt;/a&gt; are still the two major platforms that contain higher-quality courses on average. Where there are still tons of good stuff on other platforms, it can be more of a hit-or-miss experience.&lt;/p&gt;
&lt;p&gt;Another tip: for courses on platforms with reviews, take a moment to read the 1-star and 2-star ratings. While most of these reviews are nonsensical, if you notice consistent red flags, then maybe this is not the right course for you. This same approach can also be applied when assessing whether a book is worth reading.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#highly-regarded-courses-that-i-dont-recommend&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Highly Regarded Courses that I don’t recommend&lt;/h3&gt;
&lt;p&gt;Similar to university courses, the majority of online courses I’ve enrolled in have left much to be desired. Most were forgettable, filled with platitudes and lacking information density. Below are a few that were particularly problematic that I can still remember now.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.coursera.org/learn/social-psychology&quot; target=&quot;_blank&quot;&gt;Social Psychology&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Wesleyan University — Presented lots of exaggerated claims and falsified theories such as “video game causes violence.” Also quoting controversial studies such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Stanford_prison_experiment&quot; target=&quot;_blank&quot;&gt;Stanford Prison&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Milgram_experiment&quot; target=&quot;_blank&quot;&gt;Milgram experiments&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. I guess this course can serve as a cautious tale of scientific &lt;a href=&quot;https://en.wikipedia.org/wiki/Replication_crisis&quot; target=&quot;_blank&quot;&gt;progress&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and not everything you learn is true. Though since I took it in 2015, I am not sure if this course changes now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.coursera.org/learn/edinburgh-music-theory&quot; target=&quot;_blank&quot;&gt;Fundamentals of Music Theory&lt;span&gt;&lt;/span&gt;&lt;/a&gt; By the University of Edinburgh — Rudimentary lectures followed by extremely hard quizzes that are impossible to complete without a lot of extra googling&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Learning</category><category>Personal</category></item><item><title>Small Naming Tip: Use &quot;from&quot; Instead of &quot;to&quot; in Function and Variable Names</title><link>https://lesleylai.info/en/from_vs_to_in_names</link><guid isPermaLink="true">https://lesleylai.info/en/from_vs_to_in_names</guid><description>This post offers a practical tip for naming variables and functions: use &apos;from&apos; instead of &apos;to&apos; to make code more intuitive and readable.</description><pubDate>Sat, 10 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, I’m tackling a piece of code involving several mappings. Like many others, I typically label such maps as &lt;code&gt;x_to_y&lt;/code&gt;, and that’s also what I’ve done here:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value_to_var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;, (&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;usize&lt;/span&gt;&lt;span&gt;)&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var_to_num&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;usize&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// This is not a hash table but I use the index as the key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;num_to_canonical_var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vec!&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;When I need to use those maps, my code often looks like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;canonical_variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;num_to_canonical_var&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;var_to_num&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;unwrap&lt;/span&gt;&lt;span&gt;()];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As you can observe, the sequence isn’t particularly intuitive. The code executes a transformation from “variable -&amp;gt; number -&amp;gt; canonical variable,” but understanding it requires reading from the inside out, akin to unraveling a spiral.
Reading inside out can be challenging. For example, despite my nearly decade-long experience with C and C++, I still sometimes struggle to decipher the &lt;a href=&quot;https://c-faq.com/decl/spiral.anderson.html&quot; target=&quot;_blank&quot;&gt;inside-out syntax of C declarations&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Others &lt;a href=&quot;https://fuckingfunctionpointers.com/&quot; target=&quot;_blank&quot;&gt;share this sentiment&lt;span&gt;&lt;/span&gt;&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;What if I change all the &lt;code&gt;to&lt;/code&gt; to &lt;code&gt;from&lt;/code&gt;?&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;var_from_value&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;, (&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;usize&lt;/span&gt;&lt;span&gt;)&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;num_from_var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;usize&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HashMap&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;canonical_var_from_num&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vec!&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now, we can write code like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;canonical_variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;canonical_var_from_num&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;num_from_var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;unwrap&lt;/span&gt;&lt;span&gt;()];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This code is much easier to comprehend, as related names share physical proximity. Its transformation is also readily apparent just by reading from right to left.&lt;/p&gt;
&lt;p&gt;The same idea can also be applied to functions. For instance, &lt;code&gt;let shader = shader_from_file(file)&lt;/code&gt; reads better than &lt;code&gt;let shader = file_to_shader(file)&lt;/code&gt;. It isn’t a coincidence, considering that both functions (at least the pure ones) and a map data structure aim to create a mapping between data.&lt;/p&gt;
&lt;p&gt;Update 2024-02-10: Several users on Mastodon have noted that they prefer to name their map variables as &lt;code&gt;x_by_y&lt;/code&gt;, which shares similarity with the &lt;code&gt;x_from_y&lt;/code&gt; I present here.&lt;/p&gt;
&lt;p&gt;Update 2024-02-11: Another user on Mastodon mentioned that &lt;a href=&quot;https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/&quot; target=&quot;_blank&quot;&gt;Joel Spolsky wrote about the exact same suggestion&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. The article also provides an excellent description of the “Apps Hungarian” notation and how it differs from the more cumbersome “Systems Hungarian” notation that most people are familiar with. Personally, I question the relevance of even Apps Hungarian in modern languages with expressive type systems. If something possesses unique semantics and is utilized frequently enough to warrant a naming convention, we should create a strongly typed wrapper for it.&lt;/p&gt;</content:encoded><category>Coding</category><category>Opinion</category></item><item><title>What happened to Lesley in the last couple of years</title><link>https://lesleylai.info/en/2023-life-update</link><guid isPermaLink="true">https://lesleylai.info/en/2023-life-update</guid><description>A cathartic post on what happened to Lesley as of 2023. It includes why I left college, what kept me from returning, and what my life has been like since.</description><pubDate>Sun, 17 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;TL;DR: I was forced to leave university without completing my degree due to unfortunate circumstances, and returning has proven unexpectedly challenging.&lt;/p&gt;
&lt;p&gt;Update 2023/12/18: If you are reading this now, please refrain from DMing me and providing suggestions. While I appreciate your willingness to help, I find myself a bit overwhelmed at the moment.&lt;/p&gt;
&lt;p&gt;If you’re looking for tech-related content, this article is not what you seek. There’s no tech information here, so feel free to stop reading. I just share my pain here because it’s too painful to bear the weight alone.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#2021-summer-fiasco&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2021 Summer Fiasco&lt;/h2&gt;
&lt;p&gt;Until the summer of 2021, I was an international student at the University of Colorado Boulder, majoring in Computer Science and Applied Math.&lt;/p&gt;
&lt;p&gt;Unfortunately, the summer of 2021 marked a significant downturn. I should have graduated at that time, but COVID-19 isolation and remote learning severely impacted my mental health and studying ability. Nevertheless, I have only a few credits left for graduation.&lt;/p&gt;
&lt;p&gt;However, in June 2021, I misunderstood the &lt;a href=&quot;https://en.wikipedia.org/wiki/Curricular_Practical_Training&quot; target=&quot;_blank&quot;&gt;CPT&lt;span&gt;&lt;/span&gt;&lt;/a&gt; application process and unintentionally started my summer internship before obtaining authorization for my CPT. I did the same internship for two consecutive years with approval, but I got confused about the policy change that occurred in 2021, which made the process more complicated.&lt;/p&gt;
&lt;p&gt;The Office of International Student &amp;amp; Scholar Services of CU Boulder immediately canceled my &lt;a href=&quot;https://en.wikipedia.org/wiki/I-20_(form)&quot; target=&quot;_blank&quot;&gt;I-20&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and asked me to leave the U.S. immediately &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, so I purchased a flight ticket and planned to depart from the United States in June.&lt;/p&gt;
&lt;p&gt;The situation got much worse when I realized that my passport had expired. As I didn’t have any travel plans that summer due to COVID, I hadn’t bothered to check its validity. Despite reaching out to various university offices, none provided meaningful assistance. Subsequently, I contacted the Embassy of China in Chicago, but they informed me that passport renewal would be delayed and advised me to get a &lt;a href=&quot;https://en.wikipedia.org/wiki/Chinese_Travel_Document&quot; target=&quot;_blank&quot;&gt;Travel Document&lt;span&gt;&lt;/span&gt;&lt;/a&gt; as an alternative. Even this process took an extended period, and I finally received my Travel Document in late September. Then I left the US in a few days.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#after-i-went-back-to-china&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;After I went back to China&lt;/h2&gt;
&lt;p&gt;I was still optimistic when I went back to China. My COVID-induced mental health condition immediately improved as I reunited with my family. I also swiftly found a job (though officially an &lt;em&gt;intern&lt;/em&gt;). I still wanted to stay connected with the programming community, so I tried my best to attend meetups and conferences. I even gave a &lt;a href=&quot;https://youtu.be/EwC8JIJqlMc?si=Rc19yOBfGRVz4gHE&quot; target=&quot;_blank&quot;&gt;lightning talk&lt;span&gt;&lt;/span&gt;&lt;/a&gt; at CppCon 2021 despite the time difference. I also continue to organize my weekly &lt;a href=&quot;https://www.meetup.com/graphics-programming-virtual-meetup/&quot; target=&quot;_blank&quot;&gt;Graphics Programming Virtual Meetup&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to this day.&lt;/p&gt;
&lt;p&gt;Originally, I intended to return to the university in the summer of 2022. However, unforeseen family circumstances have compelled me to postpone my plans once again. At that time, I pondered the idea of not getting back at all. However, the university degree still needs to be solved. With the degree gatekeeping everywhere in China, it is hard for me to find any job besides “internships.”&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#first-half-of-2023&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;First Half of 2023&lt;/h2&gt;
&lt;p&gt;I restarted my planning to return to university early this year and intended to return this Fall. I started to communicate with my universities, but the university’s international student office proved highly challenging to communicate with. I applied for my I-20 document, necessary for a U.S. student visa, in April. However, the university staff corresponding with me continually introduced new requirements, delayed responses for a week, and requested additional tasks.&lt;/p&gt;
&lt;p&gt;The ongoing back-and-forth is exhausting. Over time, I began experiencing physical pain when reading and responding to their emails. I started to suspect that the university personnel did not want me to return at all; instead, they were only forced to process my documents out of obligation.&lt;/p&gt;
&lt;p&gt;Upon receiving my I-20 in June, I discovered it only covered half a year, and my Computer Science major was dropped. Frustrated, I reached a breaking point and sent a blunt email, pointing out what I perceived as “gaslighting” by university personnel. I requested the cancellation of the I-20 form and contemplated giving up.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#restart-application-process&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Restart Application Process&lt;/h2&gt;
&lt;p&gt;I was uncertain about my next steps and only vaguely entertained the idea of “transferring to another university to obtain a degree,” a process that could potentially take years. In October, I reluctantly chose to give my current university another chance and pleaded with them to readmit me. The process went surprisingly smoothly, and I got a new I-20 with &lt;em&gt;four years&lt;/em&gt; of duration in a short period. During the whole process, I didn’t communicate with the university’s international student office directly.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#us-visa-application&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;US Visa Application&lt;/h2&gt;
&lt;p&gt;After receiving my new I-20 form, I applied for a US visa in early December. Upon hearing my condition, the visa officer said that they would check my application and decide later. I received a rejection based on section “214(b)” in a few days.&lt;/p&gt;
&lt;p&gt;I am ready for the rejection of my visa application. After all, the entire visa application procedure operates on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Presumption_of_guilt&quot; target=&quot;_blank&quot;&gt;“presumption of guilt”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, requiring me to persuade them that I am &lt;em&gt;rich&lt;/em&gt; and definitely &lt;em&gt;harboring no immigrant intentions&lt;/em&gt;. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; My relatively older age compared to typical students and the overstaying history certainly does not work in my favor.&lt;/p&gt;
&lt;p&gt;Following the rejection, I emailed the university for assistance, requesting a letter of support. However, instead of providing any help or at least expressing sympathy, the same individual from the university’s international student office responded by forwarding the &lt;a href=&quot;https://travel.state.gov/content/travel/en/us-visas/visa-information-resources/visa-denials.html&quot; target=&quot;_blank&quot;&gt;complete content of a visa denial information page&lt;span&gt;&lt;/span&gt;&lt;/a&gt; from the US government website and declined to offer any support. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I plan to reapply for a U.S. visa shortly. However, if I face rejection again, I won’t be able to return in the spring of 2024.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#20231224-update-universitys-follow-up&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2023/12/24 Update: University’s Follow-Up&lt;/h2&gt;
&lt;p&gt;Another university personnel from its International Student and Scholar Service sent another email to me today after “come to my attention that you are frustrated with what you perceive as disinterest of the ISSS office at CU Boulder in helping you solve your visa challenges.” Someone probably forwarded this blog post to them. They “recommend that you focus on providing additional, new documents including a comprehensive explanation of your ties to home (e.g. family remaining in home country, bank accounts there, job prospects, etc.) and your intent to return there once you have completed your degree in the U.S.”&lt;/p&gt;
&lt;p&gt;I have decided not to respond to the email.&lt;/p&gt;
&lt;p&gt;It has become increasingly evident that this country and university do not welcome me. Worry not; I don’t plan to linger. At this point, even if I get a U.S. visa, I don’t intend to finish my Computer Science degree anymore&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. I will just get my Apply Math degree done and yeet myself out of their sacred country ASAP.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#202413-update-second-visa-application&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;2024/1/3 Update: Second Visa application&lt;/h2&gt;
&lt;p&gt;My second visa application was swiftly denied, indicating the likelihood of a negative record associated with my profile. To be honest, I couldn’t care less if I can’t set foot in that country ever again. Nevertheless, I must reconsider my options for pursuing a degree elsewhere.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;COVID-19 travel advisories are &lt;em&gt;not their problem&lt;/em&gt;, they said. &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Admittedly, a couple of years ago, I did want to stay in the U.S. I had a strong attachment to Boulder, having lived here for an extended period. However, my perspective has since shifted. Without a rose-colored glass, I now see institutional racism and injustices a lot clearer. &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I assumed this individual was no longer managing my case because there were no issues in September. How naive of me? &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I used to have a Computer Science and Applied Math double major. The university canceled my CS major and said that I could pursue it again after I graduate from the Applied Math one. &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Personal</category></item><item><title>Use ManuallyDrop in Rust to control drop order of structure fields</title><link>https://lesleylai.info/en/rust-manually-drop</link><guid isPermaLink="true">https://lesleylai.info/en/rust-manually-drop</guid><description>This post explains Rust&apos;s ManuallyDrop construct, and how it helps control the order of destructor calls.</description><pubDate>Mon, 06 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;First, for some context: I wrote this blog post more than a year ago but have yet to make it public since my mental health greatly degraded while I was still editing it. Now that I want to go back into blogging, I decide to release this post in its current form, though I lost interest in editing it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As programmers, “clean-up” always feels like the boring part of our code. Fortunately, in Rust, we have destructors that help us to automatically write correct, ergonomic clean-up code. However, in the rare case where the order of destruction matters, compiler-generated destructor calls can be a hindrance.&lt;/p&gt;
&lt;p&gt;In this post, I will show you how to use the Rust standard library &lt;code&gt;ManuallyDrop&lt;/code&gt; type to explicitly control how and when structure fields get dropped.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#the-problem&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The problem&lt;/h2&gt;
&lt;p&gt;Rust drops fields in the declaration order&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. For example, considering the following structure:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In this case, &lt;code&gt;first&lt;/code&gt; will be the first field to destroyed, followed by &lt;code&gt;last&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This behavior, though unintuitive (especially if you come from a C++ background&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;), is fine for most of the time, as we programmers often don’t care about exactly order of things get freed. For example, in the above example, there are no dependencies between &lt;code&gt;first&lt;/code&gt; and &lt;code&gt;last&lt;/code&gt; fields, so destroying either of them first is fine.&lt;/p&gt;
&lt;p&gt;However, there are cases where destuction-order do matters. Unless we are ok to order fields in our struct in a gratuitous reverse order, it is probably not worth relying on the compiler-generated destruction order. Worse, in some instances, we may want to interleave user code execution and the fields being dropped inside the &lt;code&gt;drop&lt;/code&gt; method, and the compiler’s automatically generated destructor calls failed us here.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#a-vulkan-example&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;A Vulkan example&lt;/h2&gt;
&lt;p&gt;I met the problem when doing some &lt;a href=&quot;https://www.vulkan.org/&quot; target=&quot;_blank&quot;&gt;Vulkan&lt;span&gt;&lt;/span&gt;&lt;/a&gt; exploration in Rust via the excellent &lt;a href=&quot;https://docs.rs/ash/latest/ash/&quot; target=&quot;_blank&quot;&gt;ash&lt;span&gt;&lt;/span&gt;&lt;/a&gt; crate. I use another crate, &lt;a href=&quot;https://crates.io/crates/gpu-allocator&quot; target=&quot;_blank&quot;&gt;gpu-allocator&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, to manage GPU memory.&lt;/p&gt;
&lt;p&gt;The topic of this post is not about the Vulkan API. If you are not familiar with it, the only thing you need to know is that the time of destruction is very important in this API, and many entities in Vulkan have implicit dependencies. Before destroying anything in Vulkan, we need to ensure that the corresponding resource is not used on the GPU. Also, we can’t destroy an object if any other objects depend on it.&lt;/p&gt;
&lt;p&gt;It is common in Vulkan applications to have a &lt;code&gt;Renderer&lt;/code&gt; structure like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gpu_allocator&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vulkan&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;Allocator&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;entry&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ash&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;Entry&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ash&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;Instance&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;physical_device&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vk&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;PhysicalDevice&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;device&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vk&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;Device&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;allocator&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Allocator&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Since the &lt;code&gt;allocator&lt;/code&gt; depends on &lt;code&gt;instance&lt;/code&gt; and &lt;code&gt;device&lt;/code&gt;, those two must be destroyed after the &lt;code&gt;allocator&lt;/code&gt;. On the other hand, certain other resources, such as buffers allocated by the &lt;code&gt;allocator&lt;/code&gt;, need to be destroyed before the &lt;code&gt;allocator&lt;/code&gt; gets destroyed.&lt;/p&gt;
&lt;p&gt;The ash crate abandons using destructors and &lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot; target=&quot;_blank&quot;&gt;RAII&lt;span&gt;&lt;/span&gt;&lt;/a&gt; all thgether but instead relies on manual resource managements inside &lt;code&gt;unsafe&lt;/code&gt; blocks. In ash, we are expected to write code like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;unsafe&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;destroy_instance&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Even though non-idiomatic in Rust, ash’s approach is fine with me. RAII combines with the Vulkan API pretty poorly for multiple reasons &lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. However, &lt;a href=&quot;https://github.com/Traverse-Research/gpu-allocator&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;gpu_allocator&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, despite depending on the ash crate, decide to implement the &lt;code&gt;Drop&lt;/code&gt; trait for its &lt;code&gt;Allocator&lt;/code&gt;. And we are in a situation where we must call the destructor of the &lt;code&gt;allocator&lt;/code&gt; in the middle of a chain of calls to &lt;code&gt;ash&lt;/code&gt;’s clean-up functions.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;All examples that &lt;code&gt;gpu_allocator&lt;/code&gt; provides write all code in the &lt;code&gt;main&lt;/code&gt; function.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In C++, we just manually call the destructors when meeting such a situation, and everything will work fine. Can we do that in Rust? Here is a try:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;impl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Drop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// ... All the allocation must be freed BEFORE the allocator get dropped&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;allocator&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;free&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;allocation&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;unwrap&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;unsafe&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;device&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;destroy_buffer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;buffer, &lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;) };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// We try to drop our allocator here&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;allocator&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// device and instance must be destroyed AFTER the allocator&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;unsafe&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;device&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;destroy_device&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;destroy_instance&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;However, Rust forbids explicit destructor calls, and the above program fails to compile. The Rust compiler then gives this “helpful” message:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;consider using &lt;code&gt;drop&lt;/code&gt; function: &lt;code&gt;drop(self.allocator)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So let’s try that:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;impl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Drop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;mem&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;allocator);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, the above solution doesn’t compile either, and it gives the “cannot move out of &lt;code&gt;self.allocator&lt;/code&gt; which is behind a mutable reference” error. The reason is that the &lt;code&gt;drop&lt;/code&gt; method takes &lt;code&gt;self&lt;/code&gt; by reference, while &lt;code&gt;std::mem::drop&lt;/code&gt; tries to borrow its field &lt;code&gt;self.allocator&lt;/code&gt;. Even though we know that our renderer will get destroyed after the &lt;code&gt;drop&lt;/code&gt; method, from the Rust type system’s perspective, &lt;code&gt;std::mem::drop&lt;/code&gt; is trying to “steal” one of its fields.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#using-option-to-circumvent-the-drop-order&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Using &lt;code&gt;Option&lt;/code&gt; to circumvent the drop order&lt;/h2&gt;
&lt;p&gt;If you are an experienced Rust programmer, you have probably already come up with an idiomatic way to our problem: making the &lt;code&gt;allocator&lt;/code&gt; field into an &lt;code&gt;Option&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;allocator&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Option&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Allocator&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then when we want to drop &lt;code&gt;self.allocator&lt;/code&gt;, we can assign it to &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;impl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Drop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;allocator &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Alternatively, we can combine a &lt;code&gt;std::mem::drop&lt;/code&gt; with a &lt;code&gt;.take()&lt;/code&gt; call: &lt;code&gt;std::mem::drop(self.allocator.take())&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Option&lt;/code&gt; solution works, and many people will probably be happy with it. However, I am dissatisfied for several reasons. Probably most importantly, the usage of &lt;code&gt;Option&lt;/code&gt; pollutes all the &lt;code&gt;self.allocator&lt;/code&gt; usage with extra &lt;code&gt;.unwrap()&lt;/code&gt; ceremony.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Option&lt;/code&gt; usage here also violates Rust’s “zero-overhead abstration” principle, as we add runtime overhead purely to satisfy the type system. Though I consider this point less important since the performance overhead of using &lt;code&gt;Option&lt;/code&gt; here is neglectable in the large picture on things.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#introducing-manuallydrop&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Introducing &lt;code&gt;ManuallyDrop&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html&quot; target=&quot;_blank&quot;&gt;std::mem::ManuallyDrop&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is a type wrapper that inhibits the Rust compiler from automatically calling the underlying type’s destructor.&lt;/p&gt;
&lt;p&gt;Let’s apply &lt;code&gt;ManuallyDrop&lt;/code&gt; to our &lt;code&gt;allocator&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;allocator&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ManuallyDrop&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Allocator&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;What makes &lt;code&gt;ManuallyDrop&lt;/code&gt; a much more ergonomic choice than &lt;code&gt;Option&lt;/code&gt; is its implementation of &lt;a href=&quot;https://doc.rust-lang.org/std/ops/trait.Deref.html&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;Deref&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, which makes it possible for us to use methods of &lt;code&gt;Allocator&lt;/code&gt; directly. A bonus point is that, unlike &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;ManuallyDrop&lt;/code&gt; doesn’t add any performance overhead.&lt;/p&gt;
&lt;p&gt;When we are done, we can use &lt;code&gt;ManuallyDrop::drop&lt;/code&gt; to drop our field. This function specifically takes a mutable reference, so we won’t have the same problem we faced with the standard &lt;code&gt;drop&lt;/code&gt; function before:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;impl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Drop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Renderer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;unsafe&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ManuallyDrop&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;drop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;allocator);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Notice that &lt;code&gt;ManuallyDrop::drop&lt;/code&gt; is an &lt;code&gt;unsafe&lt;/code&gt; function since it makes &lt;code&gt;self.allocator&lt;/code&gt; in a “zombie” state that shouldn’t be touched. But since the whole &lt;code&gt;Renderer&lt;/code&gt; structure will no longer exist after being dropped, it is not likely to pose any problem in practice.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#drawback-of-manuallydrop&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Drawback of &lt;code&gt;ManuallyDrop&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ManuallyDrop&lt;/code&gt; is perfect for the above use case, but it can cause some hassle when we can’t automatically dereference it. This case will only happen on assignment, so if we need to assign a new value to a &lt;code&gt;ManuallyDrop&lt;/code&gt; variable, we need to dereference it with &lt;code&gt;*&lt;/code&gt; explicitly:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mut&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ManuallyDrop&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;55&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This slightly annoying syntax is only a minor issue, but it does break the illusion that &lt;code&gt;ManuallyDrop&amp;lt;T&amp;gt;&lt;/code&gt; behaves exactly like the underlying type &lt;code&gt;T&lt;/code&gt;. However, the annoyance can add up if we have a lot of fields of type &lt;code&gt;ManuallyDrop&lt;/code&gt;, for example, when generating binding with C++ libraries. The good news is that there is a &lt;a href=&quot;https://github.com/rust-lang/lang-team/issues/135&quot; target=&quot;_blank&quot;&gt;proposal&lt;span&gt;&lt;/span&gt;&lt;/a&gt; that aims to provide a more ergonomic solution in the future.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ManuallyDrop&lt;/code&gt; is a seldom necessary utility in normal Rust code. Nevertheless, it is currently the ideal solution when we want explicit control of how structure fields get dropped.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://doc.rust-lang.org/reference/destructors.html&quot; target=&quot;_blank&quot;&gt;Destructors - The Rust Reference&lt;span&gt;&lt;/span&gt;&lt;/a&gt;: “The fields of a struct are dropped in declaration order.” &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C++ calls destructor in &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/destructor#Destruction_sequence&quot; target=&quot;_blank&quot;&gt;reverse declaration order&lt;span&gt;&lt;/span&gt;&lt;/a&gt; order &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In Vulkan, we don’t deleting an object until we are sure that the GPU is not using it. Deleting objects out-of-order is a big issue, and it may even crash your driver. &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Coding</category><category>Rust</category></item><item><title>CMAKE_SOURCE_DIR is probably not what you want</title><link>https://lesleylai.info/en/cmake_src_directory</link><guid isPermaLink="true">https://lesleylai.info/en/cmake_src_directory</guid><description>Today is the nth time I got bitten by CMAKE_SOURCE_DIR, so I will write it here. In short, there are two predefined variables in CMake: CMAKE_SOURCE_DIR and PROJECT_SOURCE_DIR. CMAKE_SOURCE_DIR refers to the top-level source directory that contains a CMakeLists.txt, while PROJECT_SOURCE_DIR refers t..</description><pubDate>Thu, 17 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today is the nth time I got bitten by &lt;code&gt;CMAKE_SOURCE_DIR&lt;/code&gt;, so I will write it here.
In short, there are two predefined variables in CMake: &lt;code&gt;CMAKE_SOURCE_DIR&lt;/code&gt; and &lt;code&gt;PROJECT_SOURCE_DIR&lt;/code&gt;.
&lt;code&gt;CMAKE_SOURCE_DIR&lt;/code&gt; refers to the top-level source directory that contains a &lt;code&gt;CMakeLists.txt&lt;/code&gt;,
while &lt;code&gt;PROJECT_SOURCE_DIR&lt;/code&gt; refers to the source directory of the most recent &lt;code&gt;project()&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;They are often the same, but a common workflow when using CMake is to use &lt;code&gt;add_subdirectory&lt;/code&gt; to add libraries.
And in that case, any &lt;code&gt;CMAKE_SOURCE_DIR&lt;/code&gt; in that inner library will refer to the outer project’s root rather than the library’s own root directory!
This behavior is wrong in the majority of cases, and thus we should use &lt;code&gt;PROJECT_SOURCE_DIR&lt;/code&gt; instead.&lt;/p&gt;</content:encoded><category>CMake</category><category>C++</category><category>Coding</category></item><item><title>VK_KHR_dynamic_rendering tutorial</title><link>https://lesleylai.info/en/vk-khr-dynamic-rendering</link><guid isPermaLink="true">https://lesleylai.info/en/vk-khr-dynamic-rendering</guid><description>This tutorial shows how to use the VK_KHR_dynamic_rendering extension in Vulkan. It shows the steps required to load the extension, use it, and how it affects related components such as pipeline creation</description><pubDate>Sun, 16 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.khronos.org/blog/streamlining-render-passes&quot; target=&quot;_blank&quot;&gt;Announced two months ago&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, the &lt;a href=&quot;https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_dynamic_rendering.html&quot; target=&quot;_blank&quot;&gt;dynamic rendering&lt;span&gt;&lt;/span&gt;&lt;/a&gt; Vulkan extension promises to get rid of the &lt;code&gt;VkRenderPass&lt;/code&gt; and &lt;code&gt;VkFramebuffer&lt;/code&gt; objects, which were parts of Vulkan that I “don’t understand and don’t really care about.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A trashbin that contains VkRenderPass and VkFramebuffer&quot; loading=&quot;lazy&quot; width=&quot;434&quot; height=&quot;611&quot; src=&quot;/_astro/renderpass_in_trash.B9MjWqO__19FC8S.webp&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To write a Vulkan renderer before the advent of dynamic rendering, we always needed to write a lot of boilerplate renderpass code.
It is not an ergonomic API, nor is it often that we need the flexibility of multiple subpasses or input attachments.
By contrast, the DirectX 12 API has render passes as an optional thing that is only used to “improve performance if the renderer is Tile-Based Deferred Rendering.”&lt;/p&gt;
&lt;p&gt;Recently, I started writing a new Vulkan Renderer from scratch in Rust using the &lt;a href=&quot;https://github.com/MaikKlein/ash&quot; target=&quot;_blank&quot;&gt;ash crate&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, and it was natural for me to try this shiny new dynamic rendering extension.
The resources on this extension are still sparse, and there is no tutorial on using it.
There is &lt;a href=&quot;https://github.com/SaschaWillems/Vulkan/blob/313ac10de4a765997ddf5202c599e4a0ca32c8ca/examples/dynamicrendering/dynamicrendering.cpp&quot; target=&quot;_blank&quot;&gt;Sascha Willems’ example&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, though I only found it after I implemented dynamic rendering myself.&lt;/p&gt;
&lt;p&gt;I ended up just reading the &lt;a href=&quot;https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_dynamic_rendering.html&quot; target=&quot;_blank&quot;&gt;extension spec&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, which is readable enough to figure out its usage.
I write this post, however, in a more tutorial-style approach to show how to use this extension.
To make the post more accessible, I write it using the original C-API instead of the Rust bindings.
It is good that the bindings in the &lt;code&gt;ash&lt;/code&gt; crate are a straightforward mapping to the C-API, but if I made a mistake in code snippets during the “translation” process, please get in touch with me.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#initialization&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Initialization&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;VK_KHR_dynamic_rendering&lt;/code&gt; is a device extension, so when we create our logical device, we need to enable it with other device extensions such as &lt;code&gt;VK_KHR_swapchain&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#check-extension-availability&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Check extension availability&lt;/h3&gt;
&lt;p&gt;Like all other extensions, we can check whether our physical device supports &lt;code&gt;VK_KHR_dynamic_rendering&lt;/code&gt; via &lt;code&gt;vkEnumerateDeviceExtensionProperties&lt;/code&gt;. If the result we get from &lt;code&gt;vkEnumerateDeviceExtensionProperties&lt;/code&gt; doesn’t contain &lt;code&gt;VK_KHR_dynamic_rendering&lt;/code&gt;, we will need to update the driver and &lt;a href=&quot;https://vulkan.lunarg.com/sdk/home&quot; target=&quot;_blank&quot;&gt;Vulkan SDK and runtime&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;VK_KHR_dynamic_rendering&lt;/code&gt; is young at the time of this writing (January 2021), so there is a possibility that the latest driver on your hardware still doesn’t support it.
When I wrote this article, I needed to install a &lt;a href=&quot;https://developer.nvidia.com/vulkan-driver&quot; target=&quot;_blank&quot;&gt;“Vulkan Beta Driver”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for my Nvidia card, though this is no longer the case now.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#enable-feature-and-load-the-extension&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Enable feature and load the extension&lt;/h3&gt;
&lt;p&gt;Before we create our logical device, we also need to add &lt;code&gt;VK_KHR_dynamic_rendering&lt;/code&gt; to our extension lists:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; device_extensions &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;VK_KHR_dynamic_rendering&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Additionally, dynamic rendering is hidden behind a feature flag, and we need to create a &lt;code&gt;VkPhysicalDeviceDynamicRenderingFeaturesKHR&lt;/code&gt; structure and then pass it to the &lt;code&gt;pNext&lt;/code&gt; chain when we create the logical device:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamic_rendering_feature {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.dynamicRendering &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_TRUE,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkDeviceCreateInfo device_create_info &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.pNext &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;dynamic_rendering_feature,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.enabledExtensionCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;unsigned&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;device_extensions&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.ppEnabledExtensionNames &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;device_extensions&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;If you are using C++, I recommend giving &lt;a href=&quot;https://github.com/charles-lunarg/vk-bootstrap&quot; target=&quot;_blank&quot;&gt;vk-bootstrap&lt;span&gt;&lt;/span&gt;&lt;/a&gt; library a try.
It will make the initialization process a bit smoother.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2&gt;&lt;a href=&quot;#use-dynamic-rendering-in-command-buffer&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Use dynamic rendering in command buffer&lt;/h2&gt;
&lt;p&gt;In your Vulkan renderer, you are likely to have code that looks like the following in your command buffer recording:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VK_CHECK&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;vkBeginCommandBuffer&lt;/span&gt;&lt;span&gt;(command_buffer, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;command_buffer_begin_info));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VkRenderPassBeginInfo render_pass_begin_info &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdBeginRenderPass&lt;/span&gt;&lt;span&gt;(command_buffer, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Draw calls here&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdEndRenderPass&lt;/span&gt;&lt;span&gt;(command_buffer);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VK_CHECK&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;vkEndCommandBuffer&lt;/span&gt;&lt;span&gt;(command_buffer));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With dynamic rendering, we need to replace the &lt;code&gt;VkRenderPassBeginInfo&lt;/code&gt; structure and the &lt;code&gt;vkCmdBeginRenderPass&lt;/code&gt; and &lt;code&gt;vkCmdEndRenderPass&lt;/code&gt; calls.
Instead of using &lt;code&gt;VkRenderPassBeginInfo&lt;/code&gt;, we add a &lt;a href=&quot;https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkRenderingInfoKHR.html&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;VkRenderingInfoKHR&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; structure, which looks like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VkRenderingInfoKHR&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkStructureType                        sType;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;                            pNext;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkRenderingFlagsKHR                    flags;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkRect2D                               renderArea;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;                               layerCount;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;                               viewMask;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;                               colorAttachmentCount;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkRenderingAttachmentInfoKHR&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;    pColorAttachments;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkRenderingAttachmentInfoKHR&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;    pDepthAttachment;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkRenderingAttachmentInfoKHR&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;    pStencilAttachment;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;VkRenderingInfoKHR&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You can see that some fields, like &lt;code&gt;renderArea&lt;/code&gt;, were previously provided to &lt;code&gt;VkRenderPassBeginInfo&lt;/code&gt;.
Still, the majority of the information of this structure would be provided as a part of render pass creation.
In particular, we have this new &lt;a href=&quot;https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkRenderingAttachmentInfoKHR.html&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;VkRenderingAttachmentInfoKHR&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; structure instead of &lt;a href=&quot;https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkAttachmentDescription.html&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;VkAttachmentDescription&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to describe attachments:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VkRenderingAttachmentInfoKHR&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkStructureType          sType;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;              pNext;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkImageView              imageView;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkImageLayout            imageLayout;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkResolveModeFlagBits    resolveMode;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkImageView              resolveImageView;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkImageLayout            resolveImageLayout;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkAttachmentLoadOp       loadOp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkAttachmentStoreOp      storeOp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VkClearValue             clearValue;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;VkRenderingAttachmentInfoKHR&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now we can replace our render pass code with the usage of the above structures.
This change does mean that we will write more code in our command buffer recording, as some of the information we provided to render pass object are moved to here:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VK_CHECK&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;vkBeginCommandBuffer&lt;/span&gt;&lt;span&gt;(command_buffer, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;command_buffer_begin_info));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkRenderingAttachmentInfoKHR color_attachment_info {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.imageView &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;swapchain_image_views_&lt;/span&gt;&lt;span&gt;[swapchain_image_index_],&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.imageLayout &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.loadOp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_ATTACHMENT_LOAD_OP_CLEAR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.storeOp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_ATTACHMENT_STORE_OP_STORE,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.clearValue &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; clear_value,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkRenderingInfoKHR render_info {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.renderArea &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; render_area,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.layerCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.colorAttachmentCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.pColorAttachments &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;color_attachment_info,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdBeginRenderingKHR&lt;/span&gt;&lt;span&gt;(command_buffer, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;render_info);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Draw calls here&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdEndRenderingKHR&lt;/span&gt;&lt;span&gt;(command_buffer);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VK_CHECK&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;vkEndCommandBuffer&lt;/span&gt;&lt;span&gt;(command_buffer));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#pipeline-creation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Pipeline creation&lt;/h2&gt;
&lt;p&gt;Now we are at the point where we can scrape out all of the code initializing render pass and framebuffer objects! And when creating pipeline objects, we no longer need to specify a render pass, but instead, we need to create a &lt;a href=&quot;https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPipelineRenderingCreateInfoKHR.html&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;VkPipelineRenderingCreateInfoKHR&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; object to specify attachment formats:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkPipelineRenderingCreateInfoKHR pipeline_rendering_create_info {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.colorAttachmentCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.pColorAttachmentFormats &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;swapchain_image_format_,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkGraphicsPipelineCreateInfo pipeline_create_info {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.pNext &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;pipeline_rendering_create_info,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.renderPass &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; // We no longer need a render pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#image-layout-transition&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Image layout transition&lt;/h2&gt;
&lt;p&gt;If everything were that simple, I would be very pleased with this extension.
However, it turns out that the render pass object was doing something useful.&lt;/p&gt;
&lt;p&gt;With our current code, the validation layer produces this warning every frame:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;pSwapchains[0] images passed to present must be in layout VK_IMAGE_LAYOUT_PRESENT_SRC_KHR or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR but is in VK_IMAGE_LAYOUT_UNDEFINED. The Vulkan spec states: Each element of pImageIndices must be the index of a presentable image acquired from the swapchain specified by the corresponding element of the pSwapchains array, and the presented image subresource must be in the VK_IMAGE_LAYOUT_PRESENT_SRC_KHR layout at the time the operation is executed on a VkDevice (&lt;a href=&quot;https://github.com/KhronosGroup/Vulkan-Docs/search?q=VUID-VkPresentInfoKHR-pImageIndices-01296&quot; target=&quot;_blank&quot;&gt;https://github.com/KhronosGroup/Vulkan-Docs/search?q=VUID-VkPresentInfoKHR-pImageIndices-01296&lt;span&gt;&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It says that our swapchain image is in &lt;code&gt;VK_IMAGE_LAYOUT_UNDEFINED&lt;/code&gt; layout, but to present the image, it should be in either &lt;code&gt;VK_IMAGE_LAYOUT_PRESENT_SRC_KHR&lt;/code&gt; or &lt;code&gt;VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR&lt;/code&gt;.
We can manually transition the layout of swapchain image to &lt;code&gt;VK_IMAGE_LAYOUT_PRESENT_SRC_KHR&lt;/code&gt; before presenting:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// draw calls here&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdEndRenderingKHR&lt;/span&gt;&lt;span&gt;(command_buffer);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkImageMemoryBarrier image_memory_barrier {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.srcAccessMask &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.oldLayout &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.newLayout &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.image &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;swapchain_images&lt;/span&gt;&lt;span&gt;[swapchain_image_index_],&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.subresourceRange &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.aspectMask &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_ASPECT_COLOR_BIT,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.baseMipLevel &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.levelCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.baseArrayLayer &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.layerCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdPipelineBarrier&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;command_buffer,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,&lt;/span&gt;&lt;span&gt;  // srcStageMask&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BOTTOM_OF_PIPE,&lt;/span&gt;&lt;span&gt; // dstStageMask&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; // imageMemoryBarrierCount&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;image_memory_barrier&lt;/span&gt;&lt;span&gt; // pImageMemoryBarriers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VK_CHECK&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;vkEndCommandBuffer&lt;/span&gt;&lt;span&gt;(command_buffer));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;But now &lt;code&gt;VK_IMAGE_LAYOUT_PRESENT_SRC_KHR&lt;/code&gt; is not a layout fit for rendering in the next frame.
So before rendering, we need to transition the image back into &lt;code&gt;VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;VK_CHECK&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;vkBeginCommandBuffer&lt;/span&gt;&lt;span&gt;(command_buffer, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;command_buffer_begin_info));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; VkImageMemoryBarrier image_memory_barrier {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.sType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.dstAccessMask &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.oldLayout &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_LAYOUT_UNDEFINED,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.newLayout &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.image &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;swapchain_images&lt;/span&gt;&lt;span&gt;[swapchain_image_index_],&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.subresourceRange &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.aspectMask &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VK_IMAGE_ASPECT_COLOR_BIT,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.baseMipLevel &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.levelCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.baseArrayLayer &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.layerCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vkCmdPipelineBarrier&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;command_buffer,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,&lt;/span&gt;&lt;span&gt;  // srcStageMask&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,&lt;/span&gt;&lt;span&gt; // dstStageMask&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; // imageMemoryBarrierCount&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;image_memory_barrier&lt;/span&gt;&lt;span&gt; // pImageMemoryBarriers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// begin dynamic rendering here&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// draw calls&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Almost all Vulkan renderers have helper functions for these image layout transition functions to reduce verbosity,
but it is still quite a hassle to specify all the parameters.
And we also need to do a similar layout transition dance for the depth buffer and stencil buffer, with access masks, pipeline stage masks, and layout changes accordingly.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#final-word&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Final word&lt;/h2&gt;
&lt;p&gt;In this simple case, the dynamic rendering extension seems almost as verbose as creating render passes and framebuffer objects.
Though I can see that dynamic rendering becomes more valuable in multi-pass rendering, whereas synchronization becomes complicated with the traditional render pass approach.
Khronos may also improve the ergonomics of dynamic rendering somehow in the future.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#acknowledgements&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;Special thanks to my friend &lt;a href=&quot;https://bsky.app/profile/cdgiessen.bsky.social&quot; target=&quot;_blank&quot;&gt;Charles Giessen&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for proofreading and editing this post!&lt;/p&gt;
&lt;p&gt;After this post was initially released, many experienced graphics programmers provided valuable insight and feedback.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jeremyong.com/&quot; target=&quot;_blank&quot;&gt;Jeremy Ong&lt;span&gt;&lt;/span&gt;&lt;/a&gt; provides insightful Twitter feedback on this post.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/karnkaul&quot; target=&quot;_blank&quot;&gt;Karn Kaul&lt;span&gt;&lt;/span&gt;&lt;/a&gt; mentioned that it would be more precise if I said that image layout transition for depth buffer is slightly different from color buffers. And he also noted that on some hardware and drivers, using the automatic image layout transition provided by render pass causes artifacts, and manual image layout transition is the only way anyway.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://leonbrands.software/&quot; target=&quot;_blank&quot;&gt;Leon Brands&lt;span&gt;&lt;/span&gt;&lt;/a&gt; points out that the initial post didn’t talk about pipelines, so I added a section about the change in pipeline creation.&lt;/li&gt;
&lt;li&gt;Timmy on Twitter noted that Nvidia is now shipping VK_KHR_dynamic_rendering in their game-ready drivers.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Coding</category><category>Graphics</category><category>Vulkan</category></item><item><title>How I create bilingual functionality of this blog in plain Typescript</title><link>https://lesleylai.info/en/bilingual-blog</link><guid isPermaLink="true">https://lesleylai.info/en/bilingual-blog</guid><description>This post explains how I implemented the bilingual functionality of this blog in plain Typescript.</description><pubDate>Sat, 01 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Update 2025&lt;/strong&gt;: &lt;em&gt;I’ve since migrated this blog to &lt;a href=&quot;https://astro.build/&quot; target=&quot;_blank&quot;&gt;Astro&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, but the implementation strategy of the translation remains largely unchanged.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Happy new year 2022, everyone!
Today I want to talk about something different from most of my blog posts: how I implement my bilingual blog in pure Typescript.&lt;/p&gt;
&lt;p&gt;Since I created this blog in 2015, I have always wanted to make it bilingual to reach a broader audience,
and I finally implemented it at the end of 2019.
My implementation of internationalization was probably different from most people,
as I use plain Typescript without any third-party libraries such as &lt;a href=&quot;https://www.i18next.com/&quot; target=&quot;_blank&quot;&gt;i18next&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
And I heavily rely on Typescript’s remarkable features in its type system for my implementation.&lt;/p&gt;
&lt;p&gt;My solution is probably not the most “proper” or scalable by professional standard,
but I think it fits the particular use case of a personal blog well.
It provides several significant advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The type system guarantees that it is impossible to forget to translate an entry&lt;/li&gt;
&lt;li&gt;It is very flexible as I can have arbitrarily different Javascript for different languages (Since this website is implemented in React, I can use arbitrary JSX). This is a useful property when I only want to render certain UI elements in a selected language.&lt;/li&gt;
&lt;li&gt;I don’t need to learn an i18n library just for my blog&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;
For people not familiar with JSX, it is a syntax extension of Javascript that enables us to write HTML-like UI code easily. It is designed to work together with React.js, but people also use it with other technologies such as Vue.js. [Here](https://reactjs.org/docs/introducing-jsx.html) is an introduction to JSX.
&lt;/aside&gt;
&lt;p&gt;And thus, I recommend you use a similar approach if you want to create a multilingual personal website.&lt;/p&gt;
&lt;p&gt;This blog uses the static-site generator &lt;a href=&quot;https://www.gatsbyjs.com/&quot; target=&quot;_blank&quot;&gt;GatsbyJS&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
If you are not familiar with static-site generators,
one cool thing they can perform is to transform contents in formats such as Markdown into proper HTML pages
with the help of a “template.”&lt;/p&gt;
&lt;p&gt;For blog posts,
I have separate markdown files for different languages.
For example, the Chinese version of this post and the text you are currently reading are stored in different markdown files.
However, there is still a lot of text in the “template” that needs to be translated.
Examples include my bio at the right sidebar, different menu items, and blog post tags.&lt;/p&gt;
&lt;p&gt;The “template” of GatsbyJS is in Javascript (and I decided to use Typescript, which transpiles to JS), particular React components.
As a result, it is natural for me to try to develop a Typescript solution for the internationalization problem,
and all those React components and translations will be built into static HTML.
On the other hand, suppose you use a static-site generator using Python. In that case, ideally, you should implement internationalization in Python so the translation can be done at build time to avoid the overhead of dynamically loading translation for your website.&lt;/p&gt;
&lt;p&gt;Most of my internationalization implementations are in the &lt;a href=&quot;https://github.com/LesleyLai/blog/blob/9500c49f22e886fe5aa706967e5dc4391a20ea15/src/utils/translations.tsx&quot; target=&quot;_blank&quot;&gt;translation.tsx&lt;span&gt;&lt;/span&gt;&lt;/a&gt; file:&lt;/p&gt;
&lt;p&gt;First, I have an &lt;code&gt;en&lt;/code&gt; object that stores every translation entry in English:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;en&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ai:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;AI&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;algorithms:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Algorithms&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;archive:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Archive&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Since &lt;code&gt;en&lt;/code&gt; is just a plain object, I can also store more exciting data such as jsx objects or even functions as entries:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;all_n_posts&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;All&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Link&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;`/en/archive`&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;posts&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Link&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With &lt;code&gt;en&lt;/code&gt; as an object defined, we can query its type by the &lt;code&gt;typeof&lt;/code&gt; operator:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Translations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;en&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This reflection ability is handy, and most programming languages don’t have it. Specifically, it saves us from defining the type ourselves. And it is a nice example of how a language feature helps us achieve &lt;a href=&quot;https://en.wikipedia.org/wiki/Don%27t_repeat_yourself&quot; target=&quot;_blank&quot;&gt;the DRY principle&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now with the &lt;code&gt;Translations&lt;/code&gt; type, we can create another object that mirrors the structure of &lt;code&gt;en&lt;/code&gt; object, but with an explicit type requirement:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zh&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Translations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ai:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;AI&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;algorithms:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;算法&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;archive:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;博文目录&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This way, the type system ensures that I don’t forget to translate any entries.&lt;/p&gt;
&lt;p&gt;And then, we can assemble translations of all languages into a single object. This object serves as the main entry point in our template to query specific translation entries:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;translations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;en:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;en&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;zh:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zh&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then we use the &lt;code&gt;keyof&lt;/code&gt; operator to get a union type of the keys of translation:
in this case, &lt;code&gt;&quot;en&quot; | &quot;zh&quot;&lt;/code&gt;.
&lt;code&gt;keyof&lt;/code&gt; is yet another excellent reflection feature of Typescript.
But since it expects a type rather than an object, we need to apply another &lt;code&gt;typeof&lt;/code&gt; operator before applying &lt;code&gt;keyof&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Language&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyof&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;typeof&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;translations&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I use the above union type whenever I need explicit type annotation for languages, for example, when passing the current language as a parameter.&lt;/p&gt;
&lt;p&gt;And finally, we use &lt;code&gt;Object.keys&lt;/code&gt; to get a list of languages,
so we can loop through all languages.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;languages&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;keys&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;translations&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Language&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This website is only bilingual, and I don’t know how to write in other languages.
Still, there is no hard-coding of particular languages on my implementation, except I treat English as the “default” language.
Thus, it is trivial to extend this implementation to support more languages.
The only thing need to do is to define another object with the &lt;code&gt;Translations&lt;/code&gt; type and add it as an entry to &lt;code&gt;translations&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To use translation, we first need to pass the current language of the page to its components.
Then we can use &lt;code&gt;translations[lang][&quot;entry&quot;]&lt;/code&gt; exactly where I need the translation (replace &lt;code&gt;&quot;entry&quot;&lt;/code&gt; with the entry I need).
This scheme works for functions too, as I can just call the function like &lt;code&gt;translations[lang][&quot;all_n_posts&quot;](n)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That’s it! I implemented the whole internationalization logic!
To add new entries, we just need to add translations to the &lt;code&gt;en&lt;/code&gt; and &lt;code&gt;zh&lt;/code&gt; object.
However, the most challenging part of maintaining a bilingual blog is always translating actual blog posts.
And I can’t say I did a perfect job, as indicated by the large number of English-only versions of posts on this site.
But, I’m going to keep working on it, and I hope that the technical aspect of my approach will inspire you to give it a try too!&lt;/p&gt;</content:encoded><category>Coding</category><category>i18n</category><category>Meta</category><category>TypeScript</category><category>React</category><category>Web</category></item><item><title>Little C++ Standard Library Utility: std::align</title><link>https://lesleylai.info/en/std-align</link><guid isPermaLink="true">https://lesleylai.info/en/std-align</guid><description>This blog post explains C++ standard library&apos;s std::align utility, using an arena allocator as a motivating example</description><pubDate>Mon, 13 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently learned about &lt;code&gt;std::align&lt;/code&gt;,
one of the lesser-known functions in the C++ standard library due to its limited use cases.
Since it is hard to describe without a specific use case,
I will use a simple implementation of an &lt;em&gt;arena allocator&lt;/em&gt; as a motivating example.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#arena-allocator&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Arena allocator&lt;/h2&gt;
&lt;p&gt;Arena, also called &lt;em&gt;bump allocator&lt;/em&gt; or &lt;em&gt;region-based allocator&lt;/em&gt;, is probably the most straightforward allocation strategy.
It is so widely used that even the C++ standard library has an arena implementation called &lt;a href=&quot;https://en.cppreference.com/w/cpp/memory/monotonic_buffer_resource&quot; target=&quot;_blank&quot;&gt;std::pmr::monotonic_buffer_resource&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With arena, we start with a large chunk of pre-allocated memory coming from either the stack or another allocator such as &lt;code&gt;mmap&lt;/code&gt; or &lt;code&gt;malloc&lt;/code&gt;.
Afterward, we allocate memory from that chunk by bumping a pointer offset.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;There are some confusions between an arena allocator and a &lt;em&gt;stack allocator&lt;/em&gt;.
Stack allocator is a natural evolution of the arena allocator,
where allocation in a stack allocator can be freed in a LIFO (last in, first out) order.&lt;/p&gt;&lt;/aside&gt;
&lt;figure&gt;&lt;img src=&quot;/_astro/arena_1.0XTypxak_Z1V5cwF.svg&quot; alt=&quot;Arena before allocation&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;253&quot; /&gt;&lt;figcaption&gt;Figure.1 - Arena before allocation&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;/_astro/arena_2.B0Toa7xP_Z1V5cwF.svg&quot; alt=&quot;Arena after allocation&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;253&quot; /&gt;&lt;figcaption&gt;Figure.2 - Arena after allocation&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Arena allocator has exceptional performance characteristics, especially when compared to complicated beasts like &lt;code&gt;malloc&lt;/code&gt;.
Each allocation only requires a pointer bump, and the deallocation is almost free as long as the objects allocated are &lt;em&gt;trivially destructible&lt;/em&gt;.
If we need to call destructors, we must maintain a list of objects to destroy.
Supporting destructors complicates arena implementation considerably and is beyond the scope of this post.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;In C++, a type is &lt;em&gt;trivially destructible&lt;/em&gt; if it doesn’t have a destructor that performs actions. For example, &lt;code&gt;std::string&lt;/code&gt; and &lt;code&gt;std::vector&lt;/code&gt; are not trivially destructible since their destructors free memory. Everything that contains non-trivially destructible types are also not trivially destructible.&lt;/p&gt;&lt;/aside&gt;
&lt;p&gt;The downside of the arena is that you can only free all the allocated memory at once since the arena doesn’t track each individual allocation.
Nevertheless, it is helpful in situations where we have a lot of heterogeneous allocations that only need to be freed together,
and is widely used in application domains from compilers to video games.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#a-minimum-implementation-of-an-arena&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;A minimum implementation of an arena&lt;/h2&gt;
&lt;p&gt;A straightforward implementation of the arena looks like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Arena&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::byte&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; size_remain &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (size_remain &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; size) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; alloc_ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ptr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ptr &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;size_remain &lt;/span&gt;&lt;span&gt;-=&lt;/span&gt;&lt;span&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; alloc_ptr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We can also store an end pointer instead of &lt;code&gt;size_remain&lt;/code&gt; and compare &lt;code&gt;ptr + size&lt;/code&gt; to the end pointer,
though that won’t change the overall picture too much.&lt;/p&gt;
&lt;p&gt;To use our arena, we first construct the arena from a pre-allocated buffer. Then we can allocate raw memory from the arena and create objects on top of the allocated memory:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;&lt;span&gt;::byte &lt;/span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Arena arena {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; buffer,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.size_remain &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;(buffer)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;arena&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;(ptr) &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ptr2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;arena&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ptr2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;(ptr2) &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;1729&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/new#Placement_new&quot; target=&quot;_blank&quot;&gt;placement new&lt;span&gt;&lt;/span&gt;&lt;/a&gt;s here are no-op since our types are integers,
but they are required to start the object lifetime.
Without placement new, doing assignments like &lt;code&gt;*ptr = 42&lt;/code&gt; directly is technically an undefined behavior in C++.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#alignment&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Alignment&lt;/h2&gt;
&lt;p&gt;The simple solution above would be perfect if &lt;em&gt;alignment&lt;/em&gt; doesn’t exist.
However, in the real world,
the pointer returned by &lt;code&gt;alloc&lt;/code&gt; may not be appropriately aligned for the object we want to create at that memory location.&lt;/p&gt;
&lt;p&gt;In C++, every type and object has an alignment manually controlled by &lt;code&gt;alignas&lt;/code&gt; and queried by &lt;code&gt;alignof&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Starting the lifetime of objects on unaligned locations is undefined behavior.
Depending on different architectures,
you may get slow memory access or even a mysterious crash if you try to access a misaligned object.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;See how easily undefined behavior, one of the most dreaded things among our C++ programmers, can creep in when we mess with raw memory? There is a reason why we want to encapsulate memory allocations.&lt;/p&gt;&lt;/aside&gt;
&lt;p&gt;We usually don’t care about alignment that much since the compiler can figure it out for us,
and standard library functions such as &lt;code&gt;malloc&lt;/code&gt; automatically provides sufficient alignment (&lt;code&gt;alignof(std::max_aligned_t)&lt;/code&gt;) for all allocations.
However, when we start to play with custom memory allocation strategies, alignment suddenly becomes essential to understand.&lt;/p&gt;
&lt;p&gt;Consider what our previous usage of the arena does. At first, our arena is empty.
Then we allocate a byte of memory and construct a &lt;code&gt;std::uint8_t&lt;/code&gt; on it, and everything seems totally fine.
However, when we allocate 4 bytes now, we will allocate it at the place off by one byte of the 4-bytes alignment boundary that required by &lt;code&gt;std::uint32_t&lt;/code&gt;:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;/_astro/arena_3.Dmo9Mram_ZgY18P.svg&quot; alt=&quot;Arena after allocating one uint8_t and one uint32_t&quot; loading=&quot;lazy&quot; width=&quot;439&quot; height=&quot;252&quot; /&gt;&lt;figcaption&gt;Figure.3 - Arena after two allocations&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The above example should convince you the importance of alignment when we start to get adventurous and come up with custom memory allocation strategies.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#arena-fixed&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Arena, fixed&lt;/h2&gt;
&lt;p&gt;To implement an arena that considers alignment,
we first need to have a helper function &lt;code&gt;align_forward&lt;/code&gt; that bump a given pointer forward to an aligned address given a specific alignment:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;align_forward&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::byte&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; ptr, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; alignment) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::byte&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; addr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;bit_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uintptr_t&lt;/span&gt;&lt;span&gt;&amp;gt;(ptr);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; aligned_addr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (addr &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; (alignment &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)) &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;alignment;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; ptr &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; (aligned_addr &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; addr);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/numeric/bit_cast&quot;&gt;&lt;code&gt;std::bit_cast&lt;/code&gt;&lt;/a&gt; &lt;p&gt;is a C++20 feature. Before C++20, you need &lt;code&gt;reinterpret_cast&lt;/code&gt;.&lt;/p&gt;&lt;/aside&gt;
&lt;p&gt;We first cast our pointer into an integer and then round up our (integer) address to the alignment boundary with the expression &lt;code&gt;(addr + (alignment - 1)) &amp;amp; -alignment&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To understand what this expression is doing exactly, you need to think about the meaning of the &lt;code&gt;-&lt;/code&gt; on integers in a bit-wise setting: it flips all the bits and then adds one to the result. For example, let’s say our &lt;code&gt;alignment&lt;/code&gt; is &lt;code&gt;4&lt;/code&gt;, it is represented as&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0b00000100&lt;/code&gt;,&lt;/p&gt;
&lt;p&gt;and when we apply negation, we get &lt;code&gt;-4&lt;/code&gt;, which is represented in &lt;a href=&quot;https://en.wikipedia.org/wiki/Two%27s_complement&quot; target=&quot;_blank&quot;&gt;two’s complement&lt;span&gt;&lt;/span&gt;&lt;/a&gt; as&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0b11111100&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I omitted all the leading bytes, but you should be able to see the pattern:
the negation of an alignment is precisely the bit-mask we want to mask out the lower bits.&lt;/p&gt;
&lt;p&gt;Finally, we need to cast our &lt;code&gt;aligned_addr&lt;/code&gt; back into a pointer. I choose to do some pointer arithmetic instead of doing another bit cast (&lt;code&gt;std::bit_cast&amp;lt;std::byte*&amp;gt;(aligned_addr)&lt;/code&gt;) so we don’t get &lt;a href=&quot;https://clang.llvm.org/extra/clang-tidy/checks/performance-no-int-to-ptr.html&quot; target=&quot;_blank&quot;&gt;pointer provenance warning&lt;span&gt;&lt;/span&gt;&lt;/a&gt; from clang-tidy.&lt;/p&gt;
&lt;p&gt;With the helper function in place, we can now implement our &lt;code&gt;Arena&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Arena&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::byte&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; size_remain &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aligned_alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alignment&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::byte&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; aligned_ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;align_forward&lt;/span&gt;&lt;span&gt;(ptr, alignment);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; size_for_alignment &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; aligned_ptr &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; ptr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; bump_size &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; size_for_alignment &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (size_remain &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; bump_size) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; aligned_ptr &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;size_remain &lt;/span&gt;&lt;span&gt;-=&lt;/span&gt;&lt;span&gt; bump_size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; aligned_ptr;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Notice that I changed the function name from &lt;code&gt;alloc&lt;/code&gt; to &lt;code&gt;aligned_alloc&lt;/code&gt; since we must explicitly pass an &lt;code&gt;alignment&lt;/code&gt; argument to this function. First, we call &lt;code&gt;align_forward&lt;/code&gt; to adjust our pointer to the alignment boundary in the function. And then, we calculate how many bytes we need for the allocation (which is the number of bytes used for alignment plus the actual size we need to allocate). And finally, if we have enough size to allocate, we need to bump our pointer, decrease the remaining size, and return the adjusted pointer.&lt;/p&gt;
&lt;p&gt;To use this implementation, we need to explicitly pass alignment to our arena:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;arena&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;aligned_alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;alignof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;(ptr) &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint8_t&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ptr2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;arena&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;aligned_alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;alignof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ptr2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;(ptr2) &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;1729&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You can see that our client-side code becomes a bit more nuisance to write.
However, in practice, we can hide calls to &lt;code&gt;aligned_alloc&lt;/code&gt; behind a templated function.
The important thing is that our allocations will be properly aligned:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;/_astro/arena_4.DNYKkbMj_ZgY18P.svg&quot; alt=&quot;Alignment-aware arena after allocating one uint8_t and one uint32_t&quot; loading=&quot;lazy&quot; width=&quot;439&quot; height=&quot;252&quot; /&gt;&lt;figcaption&gt;&lt;p&gt;Figure.4 - Alignment-aware arena after two allocations&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;If you still want the old &lt;code&gt;alloc&lt;/code&gt; member function that doesn’t consider alignment,
we can write it as a wrapper of &lt;code&gt;aligned_alloc&lt;/code&gt; that takes the alignment of &lt;code&gt;std::max_align_t&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aligned_alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;alignof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;max_align_t&lt;/span&gt;&lt;span&gt;), size);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This version of &lt;code&gt;alloc&lt;/code&gt; always returns pointers aligned as strictly as &lt;code&gt;std::max_align_t&lt;/code&gt;,
similar to &lt;code&gt;std::malloc&lt;/code&gt;.
This way also guarantees to have a correct alignment for each allocation,
though it can waste space if we have many allocations for small objects.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#enter-stdalign&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Enter &lt;code&gt;std::align&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The above implementation of the arena is reliable.
I use an essentially identical version of the arena in a bunch of C projects.
However, with a little bit of help from the standard library, we can do better in C++.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;std::align&lt;/code&gt; is a standard function defined in &lt;code&gt;&amp;lt;memory&amp;gt;&lt;/code&gt;. It has the following interface:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;align&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alignment&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;void*&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;space&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It does the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given a pointer &lt;code&gt;ptr&lt;/code&gt; to a buffer of size &lt;code&gt;space&lt;/code&gt;, returns a pointer aligned by the specified &lt;code&gt;alignment&lt;/code&gt; for &lt;code&gt;size&lt;/code&gt; number of bytes and decreases &lt;code&gt;space&lt;/code&gt; argument by the number of bytes used for alignment. The first aligned address is returned. — &lt;a href=&quot;https://en.cppreference.com/w/cpp/memory/align&quot; target=&quot;_blank&quot;&gt;cppreference&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The interface of &lt;code&gt;std::align&lt;/code&gt; is undoubtedly not easy to grasp,
mainly because it has two in-out parameters passed by reference.
But it serves a similar purpose as our &lt;code&gt;align_forward&lt;/code&gt; function.
The first two parameters, &lt;code&gt;alignment&lt;/code&gt; and &lt;code&gt;size&lt;/code&gt;, are the same parameters we passed to &lt;code&gt;aligned_alloc&lt;/code&gt;.
And &lt;code&gt;ptr&lt;/code&gt; and &lt;code&gt;space&lt;/code&gt; is the state of our arena.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;std::align&lt;/code&gt; starts by checking whether we have enough &lt;code&gt;space&lt;/code&gt; to allocate &lt;code&gt;size&lt;/code&gt; bytes after the alignment adjustment.
If so, it adjusts our pointer &lt;code&gt;ptr&lt;/code&gt;, decreases &lt;code&gt;space&lt;/code&gt; by the number of bytes used for alignment, and returns the aligned pointer.&lt;/p&gt;
&lt;p&gt;with &lt;code&gt;std::align&lt;/code&gt;, our code can be greatly simplified:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Arena&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; size_remain &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aligned_alloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alignment&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; res &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;align&lt;/span&gt;&lt;span&gt;(alignment, size, ptr, size_remain);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (res) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ptr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::byte&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;span&gt;(res) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;size_remain &lt;/span&gt;&lt;span&gt;-=&lt;/span&gt;&lt;span&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; res;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We no longer need our helper function, &lt;code&gt;align_forward&lt;/code&gt;, since &lt;code&gt;std::align&lt;/code&gt; serves a similar purpose.
It is nice that we don’t need to write pointer-to-integer casting and bit manipulation ourselves.
And our &lt;code&gt;aligned_alloc&lt;/code&gt; function also looks almost as simple as our initial &lt;code&gt;alloc&lt;/code&gt; function that doesn’t consider alignment.&lt;/p&gt;
&lt;p&gt;Notice that since &lt;code&gt;std::align&lt;/code&gt; only increases &lt;code&gt;ptr&lt;/code&gt; to alignment boundary and decreases &lt;code&gt;size_remain&lt;/code&gt; by the number of bytes used for alignment, we still need to change those two variables with the actual &lt;code&gt;size&lt;/code&gt; of the allocation.&lt;/p&gt;
&lt;p&gt;Another small change is that &lt;code&gt;std::align&lt;/code&gt; requires us to use &lt;code&gt;void*&lt;/code&gt; while our previous implementation uses &lt;code&gt;std::byte*&lt;/code&gt;.
Since we don’t need to do pointer arithmetics ourselves anymore, it is OK to use &lt;code&gt;void*&lt;/code&gt;, which is also the type our &lt;code&gt;aligned_alloc&lt;/code&gt; needs to return anyway.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I am not sure how many use cases &lt;code&gt;std::align&lt;/code&gt; has outside of custom allocators.
Maybe it is also helpful to implement &lt;a href=&quot;https://en.wikipedia.org/wiki/Flexible_array_member&quot; target=&quot;_blank&quot;&gt;flexible array members&lt;span&gt;&lt;/span&gt;&lt;/a&gt;-like structures.
Nevertheless, I am glad we have this little utility in the C++ standard library to save me from scratching head on manual alignment calculation.&lt;/p&gt;</content:encoded><category>Coding</category><category>C++</category></item><item><title>Fun with Ternary Search</title><link>https://lesleylai.info/en/ternary-search</link><guid isPermaLink="true">https://lesleylai.info/en/ternary-search</guid><description>This year is my first year doing the Advent of Code challenge, and today (2021 Day 7)‘s challenge is a fun one.

I won’t go to the details, but the problem involves finding the minimum for a function. The function takes an integer and returns another integer. An interesting property of that function..</description><pubDate>Tue, 07 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This year is my first year doing the &lt;a href=&quot;https://adventofcode.com/2021&quot; target=&quot;_blank&quot;&gt;Advent of Code&lt;span&gt;&lt;/span&gt;&lt;/a&gt; challenge, and today (2021 Day 7)‘s challenge is a fun one.&lt;/p&gt;
&lt;p&gt;I won’t go to the details, but the problem involves finding the minimum for a function. The function takes an integer and returns another integer. An interesting property of that function is that it has one “valley”: Everything at the left of the global minimal point monotonically decreases. Everything at the right of the global minimal point monotonically increases.&lt;/p&gt;
&lt;div&gt;
  &lt;img src=&quot;function.png&quot; alt=&quot;An illustration of the function we want to optimize&quot; /&gt;
&lt;/div&gt;
&lt;p&gt;You can think the function output as a bunch of integers like&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;100, 81, 56, 32, 16, 33, 44, 78, 129&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And we want to find out the value 16.&lt;/p&gt;
&lt;p&gt;Naively we can evaluate the function at every point in the domain and then find the minimum,
and a slightly better way is to evaluate the function until we find where the result starts to increase.
Both strategies requires &lt;code&gt;O(n)&lt;/code&gt; time, but since our data are nicely “sorted,” we can do better.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ternary-search&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Ternary Search&lt;/h2&gt;
&lt;p&gt;Ternary Search, similar to binary search, expliots our data’s pattern, and can achieve &lt;code&gt;O(log n)&lt;/code&gt; asymptotic time.
Wikipedia describe it as a technique for “finding the minimum or maximum of a unimodal function,” which is exactly the function we want to solve. The basic idea is simple: if we partition our domain into three segment by two point: &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;, then we can evaluate the function at &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; and get several cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;f(left) &amp;lt; f(right)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(left) &amp;gt; f(right)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(left) == f(right)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If &lt;code&gt;f(left) &amp;lt; f(right)&lt;/code&gt;, which means either both &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; points are greater than the position of the local minimum, or &lt;code&gt;left&lt;/code&gt; is less than the position of local minimum and &lt;code&gt;right&lt;/code&gt; is greater than the position of local minimum. In either case, we know that the local minimum is not at the right hand side of &lt;code&gt;right&lt;/code&gt;, so we can discard that part of the domain.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;f(left) &amp;gt; f(right)&lt;/code&gt;, similarly we can discard the left hand side of &lt;code&gt;left&lt;/code&gt;. And if &lt;code&gt;f(left) == f(right)&lt;/code&gt;, we can discard both side and only keep the range &lt;code&gt;[left, right]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can equally trisect the domain into &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;, and then we can run the above process recursively or iteratively to solve the problem. We still need a terminate condition: since our &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt; can be stuck if &lt;code&gt;right - left &amp;lt;= 2&lt;/code&gt;, we stop there and then fall back to linear search. And we can have the following pseudocode:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;var left = domain.min&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;var right = domain.max&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;while (right - left) &amp;gt; 3 {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;let left_third = left + (right - left) / 3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;let right_third = right - (right - left) / 3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;if f(left_third) &amp;lt; f(right_third) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;right = right_third&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} else {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;left = left_third&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for i in left until right get the smallest f(i)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It is an elegent and fun algorithm, and I am suprised that today is the first time I hear about it.
And hopefully now you also understand how and when to use this algorithm.&lt;/p&gt;</content:encoded><category>Algorithms</category></item><item><title>Don&apos;t automatically use auto parameters in C++</title><link>https://lesleylai.info/en/auto-parameters</link><guid isPermaLink="true">https://lesleylai.info/en/auto-parameters</guid><description>Since the advent of C++14, we can create lambda expressions that take auto parameters. And in C++20, we can even do the same thing for regular functions. With this feature’s advent, the programming style where all parameters are auto becomes popular among some C++ programmers. However, the feature i..</description><pubDate>Tue, 09 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Since the advent of C++14, we can create lambda expressions that take &lt;code&gt;auto&lt;/code&gt; parameters.
And in C++20, we can even do the same thing for regular functions.
With this feature’s advent,
the programming style where all parameters are &lt;code&gt;auto&lt;/code&gt; becomes popular among some C++ programmers.
However, the feature is not always optimal, and, frankly, I don’t think we should use it more often than it needs to.
In general, the more specific we make the type of a parameter, the better.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#why-do-people-like-it&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Why do people like it?&lt;/h2&gt;
&lt;p&gt;It is easier, right? Not everyone wants to write out the explicit parameter type.&lt;/p&gt;
&lt;p&gt;This can be a valid excuse when doing template-heavy generic programming,
but a lot of the time the “annoying to write” type is avoidable with some refactoring,
and we will even have higher-quality code by doing so.&lt;/p&gt;
&lt;p&gt;For example, the following is a modified version of some code I found online,
and I agree that it is annoying to write out about the explicit type of &lt;code&gt;pair&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::pair&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; pairs;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;accumulate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pairs&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;cbegin&lt;/span&gt;&lt;span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;pairs&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;cend&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;acc&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pair&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; acc &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pair&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pair&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I would also be clueless about this code’s meaning by reading this snippet
since there is no meaning attached to a pair’s &lt;code&gt;first&lt;/code&gt; and &lt;code&gt;second&lt;/code&gt; values.&lt;/p&gt;
&lt;p&gt;What if we change the element of &lt;code&gt;pairs&lt;/code&gt; into a named structure?&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Outcome&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; probability &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Outcome&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; distribution;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;accumulate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;distribution&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;cbegin&lt;/span&gt;&lt;span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;distribution&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;cend&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;acc&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Outcome&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outcome&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; acc &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outcome&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;probability&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outcome&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Suddenly, it is clear that this code tries to calculate the &lt;a href=&quot;https://en.wikipedia.org/wiki/Expected_value&quot; target=&quot;_blank&quot;&gt;expectation&lt;span&gt;&lt;/span&gt;&lt;/a&gt; of a discrete random variable!&lt;/p&gt;
&lt;p&gt;Unfortunately, instead of trying to give their code better types,
some people become so adapted to the &lt;code&gt;auto&lt;/code&gt; parameter style that they start to use it everywhere,
even in places where writing &lt;code&gt;auto&lt;/code&gt; doesn’t save keystrokes much or at all:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; v1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ...;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; v2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ...;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; smaller_ones;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;ranges&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;transform&lt;/span&gt;&lt;span&gt;(v1, v2, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;back_inserter&lt;/span&gt;&lt;span&gt;(smaller_ones),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(x, y); });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#auto-parameters-generate-templates&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Auto parameters generate templates&lt;/h2&gt;
&lt;p&gt;In some programming languages such as &lt;a href=&quot;https://en.wikipedia.org/wiki/ML_(programming_language)&quot; target=&quot;_blank&quot;&gt;ML&lt;span&gt;&lt;/span&gt;&lt;/a&gt; or Rust,
the type system can infer the exact type of a function or a lambda expression based on their definitions.
Those languages also have different type annotation syntax, which makes type annotations in parameters optional.
Thus, writing lambda expressions without parameter types in those languages is ergonomic and idiomatic.
Once users become accustomed to those languages, they often come back to C++ with the same coding style.&lt;/p&gt;
&lt;p&gt;However, in C++, unlike in those languages, the “type inference” of parameter types is just an illusion.
Template, overloading, and &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/adl&quot; target=&quot;_blank&quot;&gt;ADL&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (Argument-dependent lookup) all make such type inferences impossible.
As a result, &lt;code&gt;auto&lt;/code&gt; parameter results in unconstrained templates.
For example, we can use the amazing &lt;a href=&quot;https://cppinsights.io/&quot; target=&quot;_blank&quot;&gt;cppinsights&lt;span&gt;&lt;/span&gt;&lt;/a&gt; website to see
what &lt;code&gt;[](auto x, auto y) { return x * y + 42; });&lt;/code&gt; desuger into:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__lambda_5_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type_parameter_0_0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type_parameter_0_1&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt; /*constexpr */&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type_parameter_0_0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;type_parameter_0_1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (x &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; y) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type_parameter_0_0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type_parameter_0_1&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__invoke&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type_parameter_0_0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;type_parameter_0_1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (x &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; y) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} __lambda_5_2{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The issue is that template programming does not have the same experience as “normal” programming.
Compilers often detect type errors later than desired,
and we have worse IDE auto-completion/error detection support in template contexts.
This problem becomes more prominent when we start to write lambda expressions that are more than a one-liner
and even more so when we use &lt;code&gt;auto&lt;/code&gt; parameters for normal functions in C++20.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#unconstrained-template-can-be-dangerous&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Unconstrained template can be dangerous&lt;/h2&gt;
&lt;p&gt;Even when we need templates, constraining them is a better idea to use them.
In one of his talks, Bjarne Stroustrup mentioned that we should think about &lt;code&gt;auto&lt;/code&gt; as a &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot; target=&quot;_blank&quot;&gt;concept&lt;span&gt;&lt;/span&gt;&lt;/a&gt;— the least constraint one.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;When a template is unconstrained, it is easy to have types that accidentally match an interface.
For example, let’s say that we have a 3-dimensional vector structure,
and it is natural we would want to perform dot products on them:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Vec3&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; z &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dot&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v2&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Later, if we decide to add another 4-dimensional vector, we can invoke the same version of &lt;code&gt;dot&lt;/code&gt; that is prepared for three-dimensional vectors and get a completely unexpected result:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Vec4&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; z &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; w &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;dot&lt;/span&gt;&lt;span&gt;(Vec4{&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;}, Vec4{&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;span&gt; // expects 30, gets 14&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The C++ Core Guidelines also mentioned the danger of unconstrained templates in a highly visible scope,
especially in combination with ADL. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#explicit-type-annotation-provides-documentation-value&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Explicit type annotation provides documentation value&lt;/h2&gt;
&lt;p&gt;Even in languages without C++-specific problems,
explicit parameter types provide documentation purposes and act as “type-checking barriers” during refactoring.
That is why in ML dialects and Haskell,
top-level functions without explicit type annotation are considered bad style,
and Rust does not even allow it!&lt;/p&gt;
&lt;p&gt;When using an unfamiliar API in any statically typed language,
the type annotation is probably the first hint of what a particular function call does.
By using &lt;code&gt;auto&lt;/code&gt; parameters,
we give other people and our future selves no hint about the nature of those parameters.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;It is not always possible to avoid &lt;code&gt;auto&lt;/code&gt; parameters.
However, you should think about avoiding them, especially when your rationale for using them is nothing but convenience.&lt;/p&gt;
&lt;p&gt;Before C++20, there was no way to use concepts or explicit template annotation for lambda expressions.
Also, in some cases, the convenience and productivity gain of using &lt;code&gt;auto&lt;/code&gt; parameters outweigh its drawbacks.
However, I think the downside is severe enough to consider auto parameters a code smell.
When meeting code with auto parameters, we should always ask, “Is it possible to use a concrete type here?”
And if it is not the case, then the next question is, “Is it possible to use a concept here?”&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/HddFGPTAmtU&quot; target=&quot;_blank&quot;&gt;CppCon 2018: Bjarne Stroustrup “Concepts: The Future of Generic Programming (the future is here)”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rt-visible&quot; target=&quot;_blank&quot;&gt;T.47: Avoid highly visible unconstrained templates with common names&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Coding</category><category>C++</category><category>Opinion</category></item><item><title>Using default parameters to circumvent the type system is an anti-pattern</title><link>https://lesleylai.info/en/default-parameter-antipattern</link><guid isPermaLink="true">https://lesleylai.info/en/default-parameter-antipattern</guid><description>I am doing some peer programming for a university course project today. In our codebase, we have a Ship class like the following:



Later, the new requirement of the course project requires us to add another field, what we called captainsQuertersHealth, to the class, so we made the following change..</description><pubDate>Fri, 26 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am doing some peer programming for a university course project today.
In our codebase, we have a &lt;code&gt;Ship&lt;/code&gt; class like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hitCount&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; name;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; length;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// other methods&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Later, the new requirement of the course project requires us to add another field, what we called &lt;code&gt;captainsQuertersHealth&lt;/code&gt;, to the class,
so we made the following change:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hitCount&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// highlight-start&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;captainsQuertersHealth&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// highlight-end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// highlight-start&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;captainsQuertersHealth&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// highlight-end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; name;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; length;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// highlight-start&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;captainsQuertersHealth&lt;/span&gt;&lt;span&gt; captainsQuertersHealth;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// highlight-end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// other methods&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;However, we had tons of unit tests that test against the old interface and they don’t care about the &lt;code&gt;captainsQuertersHealth&lt;/code&gt; field.
My partner suggested adding a default parameter.
Since the course project is in Java, which doesn’t support default parameters by default, he recommends adding an overloaded constructor:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; name, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; length) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;(name, length, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This constructor delegates to the previous constructor and always default &lt;code&gt;captainsQuertersHealth&lt;/code&gt; to one.
It is certainly convenient.
However, adding this constructor means that the compiler will not be able to generate a compile-time error at places where we use this constructor,
and at those places, we do care about &lt;code&gt;captainsQuertersHealth&lt;/code&gt;.
As a result, it would postpone a compiler catchable bug to runtime.&lt;/p&gt;
&lt;p&gt;I convinced my teammate that it was a bad idea.
And our final solution was to add a helper in unit tests:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;createShip&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; name, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; length) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ship&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;, length, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I am not saying that you shouldn’t use default parameters or function overloading, but do notice their shortcoming and use them judiciously.&lt;/p&gt;</content:encoded><category>Coding</category><category>Java</category><category>OOP</category><category>Opinion</category></item><item><title>What is std::function in C++, and why do we need them?</title><link>https://lesleylai.info/en/std-function</link><guid isPermaLink="true">https://lesleylai.info/en/std-function</guid><description>Yesterday, someone in the #include&lt;C++&gt; discord server asked the following question:

&gt; how std::function works with lambda captures and functions handling I still don’t understand

Below was my answer to the question, with some typo-fixes and expansions:


INVOCABLES CAN HAVE DIFFERENT TYPES EVEN I..</description><pubDate>Mon, 18 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Yesterday, someone in the &lt;a href=&quot;https://www.includecpp.org/discord/&quot; target=&quot;_blank&quot;&gt;#include&amp;lt;C++&amp;gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; discord server asked the following question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;how &lt;code&gt;std::function&lt;/code&gt; works with lambda captures and functions handling I still don’t understand&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Below was my answer to the question, with some typo-fixes and expansions:&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#invocables-can-have-different-types-even-if-their-parameter-and-return-types-are-the-same&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Invocables can have different types even if their parameter and return types are the same&lt;/h2&gt;
&lt;p&gt;In C++, lambda expressions can be considered syntactic sugar over classes with &lt;code&gt;operator()&lt;/code&gt; defined. For example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; lambda &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; y; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;is roughly equivalent to&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__Lambda&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; y;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; lambda &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; __Lambda { .x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; x };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;One consequence is that every lambda expression has a distinct type. For example, in the below snippet,&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x, z;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; lambda &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; y; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; lambda2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;z&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; z; };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;lambda&lt;/code&gt; and &lt;code&gt;lambda2&lt;/code&gt; have different types, even though they both take an &lt;code&gt;int&lt;/code&gt; and return an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;C++ also have functions,
which are distinct from classes with &lt;code&gt;operator()&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#the-motivation-for-stdfunction&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The motivation for &lt;code&gt;std::function&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Then, how do we store such an invocable object that takes an int and returns an int disregard of its types?&lt;/p&gt;
&lt;p&gt;We need &lt;code&gt;std::function&lt;/code&gt; to accomplish such a task. For example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; func;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A canonical use case for storing an invocable in this fashion is a task system,
where you probably want to store callbacks in a container to execute later:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TaskQueue&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::queue&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; queue;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::mutex mutex;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::condition_variable ready;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// member functions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#type-erasure&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Type Erasure&lt;/h2&gt;
&lt;p&gt;To make &lt;code&gt;func&lt;/code&gt; accepts both &lt;code&gt;lambda&lt;/code&gt; and &lt;code&gt;lambda2&lt;/code&gt;,
&lt;code&gt;std::function&lt;/code&gt; needs to have constructors that take any function object or plain function that satisfies its signature.
And we need to perform &lt;em&gt;type erasure&lt;/em&gt; to achieve this behavior.&lt;/p&gt;
&lt;p&gt;There are various techniques to implement type erasure in C++,
and it is not a topic I can fit into this post.
But the high-level idea is that &lt;code&gt;std::function&lt;/code&gt; needs some function pointer that can invoke the invocable and some storage space to store lambda captures (or data members of a function object).
The data need to be allocated on the heap since lambda expressions (or invocable classes) can have arbitrary sized capture.
However, all major &lt;code&gt;std::function&lt;/code&gt; implementations also perform &lt;em&gt;small buffer optimization&lt;/em&gt; if your lambda is small enough to fit into a predefined capacity.
In that case, all data can be allocated directly inside the &lt;code&gt;std::function&lt;/code&gt; object itself, and no additional heap allocation is performed.&lt;/p&gt;</content:encoded><category>C++</category><category>Coding</category></item><item><title>Resources that help you to delve into C++</title><link>https://lesleylai.info/en/delve_into_cpp</link><guid isPermaLink="true">https://lesleylai.info/en/delve_into_cpp</guid><description>This post offers practical tips and curated resources for learning C++, tailored to different backgrounds and experience levels.</description><pubDate>Fri, 15 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;I already received some great feedback for this post, and any further feedbacks, error-correction, and resource recommendation are welcome. One way to contact me is to direct message me (&lt;a href=&quot;https://mastodon.gamedev.place/@lesley&quot; target=&quot;_blank&quot;&gt;@lesley@mastodon.gamedev.place&lt;span&gt;&lt;/span&gt;&lt;/a&gt;) on Mastodon&lt;/em&gt;.&lt;/p&gt;
&lt;aside&gt;
Thanks to Shafik Yaghmour, Kate Greogory, and Dwight Browne
&lt;/aside&gt;
&lt;p&gt;&lt;em&gt;Update 2021-03-29: Add a bunch of resources.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;During the years, a lot of people ask me for help in learning C++.
I am no C++ expert,
but as a person who is doing C++ for years,
I want to share a bunch of beginner-friendly C++ resources that are known to be of high quality.
And hopefully this list of resources can help learners who are new to C++.&lt;/p&gt;
&lt;p&gt;When anyone asks me for guidance about getting into C++,
I always ask first about their existing experiences.
Some people just start to learn programming and decide to learn C++ as their first language,
some people have learned a limited amount of C++ and want to learn more,
and some of them are already programming veterans in other languages.
Depend on your experiences,
you probably want to start with different materials,
and I try to cater to each of those backgrounds in this post.&lt;/p&gt;
&lt;p&gt;One thing I want to mention, though, is that reading books or watching videos all the time is not the best strategy to learn.
Whatever stage you are in, it is much easier to learn when you apply ideas into code,
so spending time on coding projects helps.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#what-if-i-just-start-learning-to-program-and-choose-c-as-my-first-language&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;What if I just start learning to program and choose C++ as my first language?&lt;/h2&gt;
&lt;p&gt;For beginners, it is important to only “learn from the best” since it is hard to discern if your tutorial is making mistakes or encouraging bad practices.&lt;/p&gt;
&lt;p&gt;For books, I recommend Bjarne Stroustrup (the creator of C++) ‘s &lt;a href=&quot;https://www.amazon.com/Programming-Principles-Practice-Using-C/dp/0138308683&quot; target=&quot;_blank&quot;&gt;“Programming: Principles and Practice Using C++ 3rd edition”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; as a starting point.
The book is thick, so don’t feel guilty if you cannot finish the whole book.&lt;/p&gt;
&lt;p&gt;If you are more inclined toward tutorial videos,
look at Kate Gregory’s &lt;a href=&quot;https://www.pluralsight.com/courses/learn-program-cplusplus&quot; target=&quot;_blank&quot;&gt;Learn to Program with C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
If you join the &lt;a href=&quot;https://www.includecpp.org/discord/&quot; target=&quot;_blank&quot;&gt;#include&amp;lt;C++&amp;gt; discord server&lt;span&gt;&lt;/span&gt;&lt;/a&gt;,
You can also message her there to get a trial code.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#what-if-i-already-learned-some-c-before-and-want-to-delve-in-deeper&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;What if I already learned some C++ before and want to delve in deeper?&lt;/h2&gt;
&lt;p&gt;What if you have some limited C++ experience before?
Maybe you already learned some C++ from your university data structure course,
or perhaps you followed some online tutorials that use C++.
From my personal experiences and what I heard,
most university programming courses or those online tutorials teach problematic practices, and the instructors often do not have a good grasp of the language.
Thus, “learn from the best materials” is especially important for you to offset prior misconceptions on C++.&lt;/p&gt;
&lt;p&gt;For books, I will still recommend either Bjarne Stroustrup’s &lt;a href=&quot;https://www.amazon.com/Programming-Principles-Practice-Using-C/dp/0138308683&quot; target=&quot;_blank&quot;&gt;“Programming: Principles and Practice Using C++ 3rd edition”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
And for video tutorials, you can try Kate Gregory’s &lt;a href=&quot;https://www.pluralsight.com/courses/c-plus-plus-foundations&quot; target=&quot;_blank&quot;&gt;C++ Foundations&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#what-if-i-am-a-veteran-in-another-language-and-want-to-delve-into-c&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;What if I am a veteran in another language and want to delve into C++?&lt;/h2&gt;
&lt;p&gt;If you are already a proficient programmer in some other languages and want to delve into C++,
you can choose materials with faster pace.&lt;/p&gt;
&lt;p&gt;As for book recommendations,
Bjarne Stroustrup’s &lt;a href=&quot;https://www.stroustrup.com/4th.html&quot; target=&quot;_blank&quot;&gt;“The C++ Programming Language (4th Edition)”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; was one of the best-written books I ever read,
though do notice that this book was written with C++11 and misses some of the later developments.
The book is also very thick, so if you want a newer and shorter introduction, try &lt;a href=&quot;https://www.stroustrup.com/tour3.html&quot; target=&quot;_blank&quot;&gt;”)”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#i-think-that-i-have-a-decent-grasp-of-c-whats-next&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;I think that I have a decent grasp of C++. What’s next?&lt;/h2&gt;
&lt;p&gt;So you spend months with the above materials,
and feel that you have a decent grasp of basic C++ concepts.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;For experienced C++ folks, no, I am not talking about &lt;em&gt;that &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot; target=&quot;_blank&quot;&gt;concept&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/em&gt; 😃.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;A sanity check to make sure about your understanding of C++ is whether you are familiar with the following topics,
to name a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how to use &lt;code&gt;const&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;templates&lt;/li&gt;
&lt;li&gt;references and pointers&lt;/li&gt;
&lt;li&gt;usage of the standard library, in particular, iterators and algorithms&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/language/raii&quot; target=&quot;_blank&quot;&gt;RAII&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;destructor&lt;/li&gt;
&lt;li&gt;copy and move constructor and assignment&lt;/li&gt;
&lt;li&gt;move semantics&lt;/li&gt;
&lt;li&gt;operator overloading&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;c++-lambda&quot;&gt;lambda expressions and function objects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;undefined behaviors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it is time to put C++ into practical usage.
C++ is used for diverse purposes,
and using C++ in specific areas is probably more critical than the C++ language itself.
It is perhaps also a good time to spend some time on the broader C++ ecosystems, like testing libraries such as &lt;a href=&quot;https://github.com/catchorg/Catch2&quot; target=&quot;_blank&quot;&gt;Catch2&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, build system generators such as &lt;a href=&quot;https://cmake.org/&quot; target=&quot;_blank&quot;&gt;CMake&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, and package managers such as &lt;a href=&quot;https://conan.io/&quot; target=&quot;_blank&quot;&gt;Conan&lt;span&gt;&lt;/span&gt;&lt;/a&gt; or &lt;a href=&quot;https://github.com/microsoft/vcpkg&quot; target=&quot;_blank&quot;&gt;vcpkg&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another thing to consider is to start learning another programming language,
especially for folks who only know C++ at this point.
Good next languages to pick are those very different from C++,
for example,
dynamically-typed languages such as Javascript, Python, or a Lisp dialect.&lt;/p&gt;
&lt;p&gt;That being said, there is still &lt;em&gt;a lot&lt;/em&gt; to learn about the C++ language itself. And I will try to list some resources that are still relative up-to-date and I enjoyed:&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#books&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Books&lt;/h3&gt;
&lt;p&gt;If you haven’t read &lt;a href=&quot;https://www.stroustrup.com/4th.html&quot; target=&quot;_blank&quot;&gt;“The C++ Programming Language (4th Edition)”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, I would still recommend it. And here is a bunch of other books I would like to recommend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996&quot; target=&quot;_blank&quot;&gt;“Effective Modern C++”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Scott Mayer&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://leanpub.com/cppbestpractices&quot; target=&quot;_blank&quot;&gt;“C++ Best Practices”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Jason Turner&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cppstd17.com/&quot; target=&quot;_blank&quot;&gt;“C++17 - The Complete Guide”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Nicolai M. Josuttis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some books focus on specific areas of the language, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tmplbook.com/&quot; target=&quot;_blank&quot;&gt;“C++ Templates - The Complete Guide, 2nd Edition”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by David Vandevoorde, Nicolai M. Josuttis, and Douglas Gregor&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Mastering-17-STL-standard-components/dp/178712682X&quot; target=&quot;_blank&quot;&gt;“Mastering the C++17 STL”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Arthur O’Dwyer&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/functional-programming-in-c-plus-plus&quot; target=&quot;_blank&quot;&gt;“Functional Programming in C++”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Ivan Čukić&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/c-plus-plus-concurrency-in-action-second-edition&quot; target=&quot;_blank&quot;&gt;“C++ Concurrency in Action, 2nd edition”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Anthony Williams&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#conference-videos&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conference Videos&lt;/h3&gt;
&lt;p&gt;Conference videos are also an excellent resource to learn more about C++. They focus on a diversity of topics; many of them are hard to find in books. And they also require low commitment (just spend an hour lunchtime watching some videos)&lt;/p&gt;
&lt;p&gt;Here are some of my favorites that are also beginner-friendly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=MBRoCdtZOYg&quot; target=&quot;_blank&quot;&gt;CppCon 2019: Kate Gregory “Naming is Hard: Let’s Do Better”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=n0Ak6xtVXno&quot; target=&quot;_blank&quot;&gt;CppCon 2018: Kate Gregory “Simplicity: Not Just For Beginners”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/XkDEzfpdcSg&quot; target=&quot;_blank&quot;&gt;CppCon 2017: Kate Gregory “10 Core Guidelines You Need to Start Using Now”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=bSkpMdDe4g4&quot; target=&quot;_blank&quot;&gt;CppCon 2017: Matt Godbolt “What Has My Compiler Done for Me Lately? Unbolting the Compiler’s Lid”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning&quot; target=&quot;_blank&quot;&gt;Going Native 2013: Sean Parent “C++ Seasoning”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/xnqTKD8uD64&quot; target=&quot;_blank&quot;&gt;CppCon 2014: Herb Sutter “Back to the Basics! Essentials of Modern C++ Style”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/1OEu9C51K2A&quot; target=&quot;_blank&quot;&gt;CppCon 2015: Bjarne Stroustrup “Writing Good C++14”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/DHOlsEd0eDE&quot; target=&quot;_blank&quot;&gt;CppCon 2018: Jason Turner “Applied Best Practices”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/nnY4e4faNp0&quot; target=&quot;_blank&quot;&gt;CppCon 2017: Jason Turner “Practical C++17”&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;#communities&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Communities&lt;/h3&gt;
&lt;p&gt;Many people in the C++ community, and I am always willing to answer direct messaging questions. However, I, or most people you can contact online, have limited experiences.&lt;/p&gt;
&lt;p&gt;To utilize the best wisdom of people,
you need to join programming communities,
and then you can ask questions in public and get a response from multiple people. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Being active in programming communities also has numerous other benefits, including getting job information and having more social support.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#includec&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;#include&amp;lt;C++&amp;gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://www.includecpp.org/&quot; target=&quot;_blank&quot;&gt;#include&amp;lt;C++&amp;gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is a wonderful community to join.
Its mission includes providing conference scholarship to people in need,
but for most people,
you can join &lt;a href=&quot;https://www.includecpp.org/discord/&quot; target=&quot;_blank&quot;&gt;its discord server&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to hang out and talk about C++.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#local-meetups&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Local Meetups&lt;/h4&gt;
&lt;p&gt;Joining &lt;a href=&quot;https://www.meetup.com/North-Denver-Metro-C-Meetup/&quot; target=&quot;_blank&quot;&gt;North Denver Metro C++ Meetup&lt;span&gt;&lt;/span&gt;&lt;/a&gt; was one of the best decisions for me during my college years.
I understand that it is a hard time to pop into meetups at the time of writing since most of them are currently held online.
Nevertheless, I urge you to try to attend some meetups if you have time.
Online meetings also provide some advantages compare to physical ones.
For example, they require low commitment, and you can choose from all of those meetups worldwide.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#attending-conferences&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Attending Conferences&lt;/h4&gt;
&lt;p&gt;If you are serious about C++, then conferences are great places to meet like-minded people.
There are C++ conferences around the globe.&lt;/p&gt;
&lt;p&gt;Same as meetups, one difficulty at the time of writing is that most C++ conferences are hosted online, but they are still worthwhile to consider.
Here are some of the recurring C++ conferences or conferences that heavily feature C++, with their Twitter handle and Youtube Channel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cppcon.org/&quot; target=&quot;_blank&quot;&gt;CppCon&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/user/CppCon&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (U.S.-based)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cppnow.org/&quot; target=&quot;_blank&quot;&gt;C++Now&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/user/BoostCon&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (U.S.-based, tuned toward a more advanced audience)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://accu.org/conf-main/main/&quot; target=&quot;_blank&quot;&gt;ACCU&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UCJhay24LTpO1s4bIZxuIqKw&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (UK-based, different programming languages, but has a lot of C++ contents)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://meetingcpp.com/&quot; target=&quot;_blank&quot;&gt;Meeting C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/user/MeetingCPP&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (German-based)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.embo.io&quot; target=&quot;_blank&quot;&gt;emBO++&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UCg2JbpJ-PGdFUEZEiNr0GWg&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (German-based)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cpponsea.uk/&quot; target=&quot;_blank&quot;&gt;C++ on Sea&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UCAczr0j6ZuiVaiGFZ4qxApw&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (UK-based)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://corecpp.org/&quot; target=&quot;_blank&quot;&gt;Core C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UCE14XYFaK1fDTnOTqlOFrrQ&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (Israel-based)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.codedive.pl&quot; target=&quot;_blank&quot;&gt;Code::Dive&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UCU0Rt8VHO5-YNQXwIjkf-1g/videos&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (Poland-based)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.codeeurope.pl/&quot; target=&quot;_blank&quot;&gt;Code Europe&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UChdVVEAilVHULlycMbqRpdg/&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (Poland-based, different programming languages)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ndcconferences.com/&quot; target=&quot;_blank&quot;&gt;NDC Conferences&lt;span&gt;&lt;/span&gt;&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/channel/UCTdw38Cw6jcm0atBPA39a0Q/&quot; target=&quot;_blank&quot;&gt;Youtube&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] (Multiple locations, different programming languages) &lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is &lt;a href=&quot;https://isocpp.org/wiki/faq/conferences-worldwide&quot; target=&quot;_blank&quot;&gt;a list of conferences&lt;span&gt;&lt;/span&gt;&lt;/a&gt; on the ISO C++ website.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;#listening-to-podcasts&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Listening to Podcasts&lt;/h4&gt;
&lt;p&gt;There are a bunch of C++ podcasts, including a few new ones appeared in 2020:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cppcast.com/&quot; target=&quot;_blank&quot;&gt;CppCast&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cpp.chat/&quot; target=&quot;_blank&quot;&gt;cpp.chat&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tlbh.it/&quot; target=&quot;_blank&quot;&gt;TLB Hit&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://adspthepodcast.com/&quot; target=&quot;_blank&quot;&gt;ADSP: The Podcast&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nodiagnosticrequired.tv/&quot; target=&quot;_blank&quot;&gt;No Diagnostic Required&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.twoscomplement.org/&quot; target=&quot;_blank&quot;&gt;Two’s Complement&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;a href=&quot;#following-blogs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Following Blogs&lt;/h4&gt;
&lt;p&gt;I use RSS to keep track of the tech blogs,
and I highly recommend you try out RSS too.&lt;/p&gt;
&lt;p&gt;I follow hundreds of blogs &lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, including C++ and various other topics.
Here are some of the best C++ ones that pops into my head:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fluentcpp.com/&quot; target=&quot;_blank&quot;&gt;Fluent C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://herbsutter.com/&quot; target=&quot;_blank&quot;&gt;Sutter’s Mill&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.modernescpp.com/&quot; target=&quot;_blank&quot;&gt;Modernes C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://thephd.github.io/&quot; target=&quot;_blank&quot;&gt;The Pasture&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://foonathan.net/&quot; target=&quot;_blank&quot;&gt;foonathan::​blog()&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://brevzin.github.io/&quot; target=&quot;_blank&quot;&gt;Barry Revzin&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://artificial-mind.net/&quot; target=&quot;_blank&quot;&gt;artificial::mind&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.bfilipek.com/&quot; target=&quot;_blank&quot;&gt;Bartek’s coding blog&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arne-mertz.de/&quot; target=&quot;_blank&quot;&gt;Simplify C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://videocortex.io/&quot; target=&quot;_blank&quot;&gt;Video Cortex&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shafik.github.io/&quot; target=&quot;_blank&quot;&gt;Shafik Yaghmour&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;
&lt;p&gt;This blog also has an &lt;a href=&quot;https://lesleylai.info/rss.xml&quot; target=&quot;_blank&quot;&gt;RSS feed&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Do notice that blogs sometimes can talk about very advanced topics.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#misc-resources&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Misc resources&lt;/h3&gt;
&lt;p&gt;Here are some misc resources that are also worth mentioning.
Some of those are great online tools, while others are video series.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/&quot; target=&quot;_blank&quot;&gt;cppreference&lt;span&gt;&lt;/span&gt;&lt;/a&gt; should be your go-to site for C++ language and standard library reference, and it is usually a lot more accurate and up-to-date than its alternatives.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://compiler-explorer.com/&quot; target=&quot;_blank&quot;&gt;Compiler Explorer&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an online coding environment that supports C++ and a dozen other languages. It can show the compiled assembly of your program and run your program. Unlike most online C++ coding environments, which often ship with an outdated compiler, there are many compilers to choose from in compiler explorer, including the most cutting-edge ones.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://quick-bench.com/&quot; target=&quot;_blank&quot;&gt;Quick C++ benchmark&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an online tool to perform quick benchmarks on C++.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cppinsights.io/&quot; target=&quot;_blank&quot;&gt;C++ Insights&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an invaluable tool to show how compilers translation “syntactic sugar” such as lambda expressions and range-based for-loop behind the scenes. I used it in my &lt;a href=&quot;/en/c++-lambda&quot;&gt;C++ lambda tutorial&lt;/a&gt; post.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://abseil.io/tips/&quot; target=&quot;_blank&quot;&gt;C++ Tips of the week&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pluralsight.com/courses/beautiful-cplusplus-stl-algorithms&quot; target=&quot;_blank&quot;&gt;Kate Gregory’s STL Algorithms course&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is a great resource to learn more about and appreciate C++ standard algorithms.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCxHAlbZQNFU2LgEtiqd2Maw&quot; target=&quot;_blank&quot;&gt;C++ Weekly&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is a Youtube channel on various C++ topics, posted weekly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#references-and-further-reading&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;References and further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;“SG20 Education And Recommended Videos For Teaching C++”. Christopher Di Bella&lt;/em&gt;, 2021, &lt;a href=&quot;https://www.cjdb.com.au/sg20-and-videos&quot; target=&quot;_blank&quot;&gt;https://www.cjdb.com.au/sg20-and-videos&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Accessed 15 Jan 2021.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“References And Links”. #Include {’&amp;lt;‘}C++{’&amp;gt;’}&lt;/em&gt;, 2021, &lt;a href=&quot;https://www.includecpp.org/resources/references/&quot; target=&quot;_blank&quot;&gt;https://www.includecpp.org/resources/references/&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Accessed 16 Jan 2021.&lt;/li&gt;
&lt;li&gt;Yaghmour, Shafik. &lt;em&gt;“Where To Get Started Learing C++ And What Resources To Use”. Shafik Yaghmour’s Blog&lt;/em&gt;, 2019, &lt;a href=&quot;https://shafik.github.io/c++/learning/2019/09/05/getting_started_learning_cpp.html&quot; target=&quot;_blank&quot;&gt;https://shafik.github.io/c++/learning/2019/09/05/getting_started_learning_cpp.html&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Accessed 16 Jan 2021.&lt;/li&gt;
&lt;/ul&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Asking questions online is an art, and a poorly phrased question makes people don’t know how to respond. Further, people are often too polite to point out that a question is poorly phrased. Kate Gregory’s &lt;a href=&quot;http://www.gregcons.com/KateBlog/HowToAskForCCodingHelp.aspx&quot; target=&quot;_blank&quot;&gt;How to ask for C++ coding help&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an excellent read on how to ask for help online. &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some of the links above are collected from &lt;a href=&quot;https://github.com/shafik/cpp_youtube_channels/blob/master/README.md&quot; target=&quot;_blank&quot;&gt;shafik/cpp_youtube_channels&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you want to see all the blogs I follow, visit &lt;a href=&quot;https://gist.github.com/LesleyLai/549f45fb0dfdf6ab31e6ffadaeaddb10&quot; target=&quot;_blank&quot;&gt;this gist&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Coding</category><category>C++</category><category>Learning</category></item><item><title>Factual errors in &quot;These Modern Programming Languages Will Make You Suffer&quot;, and why it is a suffer to read</title><link>https://lesleylai.info/en/factual-errors-in-modern-language-sucks</link><guid isPermaLink="true">https://lesleylai.info/en/factual-errors-in-modern-language-sucks</guid><description>Today I stumble upon an article These Modern Programming Languages Will Make You Suffer after Twitter outrage. The post is absurd and indeed a suffer to read for me. However, it also receives 1k+ medium claps at the time of writing, and I cannot stay silent.

In essence, this article tries to promot..</description><pubDate>Tue, 08 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today I stumble upon an article &lt;a href=&quot;https://medium.com/better-programming/modern-languages-suck-ad21cbc8a57c&quot; target=&quot;_blank&quot;&gt;These Modern Programming Languages Will Make You Suffer&lt;/a&gt;
after Twitter outrage.
The post is absurd and indeed a suffer to read for me.
However, it also receives 1k+ medium claps at the time of writing, and I cannot stay silent.&lt;/p&gt;
&lt;p&gt;In essence, this article tries to promote functional languages and list their advantages.
As an FP fanboy myself, I love content that encourages the usage of functional programming.
However, this article is so biased and full of factual errors, to the degree that it only shows the author’s lack of understanding in both the languages they hate and the languages they try to promote. And I am not even surprised to find that the author was behind another notorious medium clickbait, &lt;a href=&quot;https://medium.com/better-programming/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7&quot; target=&quot;_blank&quot;&gt;Object-Oriented Programming - The Trillion Dollar Disaster&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will not focus on this article’s opinions.
Various Twitter shitposts sometimes have more extreme views than this article.
Also, it is hard to criticize objectively on buzzwords such as “bad” or “a mess.”
Instead, let’s focus on the misleading factual errors.
Though I am sure that there are still many more factual errors in the section I missed or in languages where I don’t have experience.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#pure-functions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Pure functions&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Functions that do not mutate(change) any state are called &lt;em&gt;pure&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pure functions are &lt;em&gt;deterministic&lt;/em&gt; and have &lt;em&gt;no side-effect&lt;/em&gt;.
“Do not mutate” is way not enough to make a function “pure.”&lt;/p&gt;
&lt;p&gt;Surprisingly, the author has a correct description of pure function later in the post,
and similar discrepancy also happened more than once,
which made me wonder whether a large chunk of the article is “borrowed” from elsewhere.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#c&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;C++&lt;/h2&gt;
&lt;p&gt;C++ is the perfect punch bag for a lot of reasons,
but still, you shouldn’t bash on a language if you have no understanding of it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The developers have to worry about manually releasing and allocating memory.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do you know what &lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot; target=&quot;_blank&quot;&gt;RAII&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is? And have you ever used C++ or Rust before? The same argument can go to the author’s rant on the lack of GC in Rust.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;has only rudimentary concurrency mechanisms&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let me reply with a tweet from Bryce Lelbach.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Almost everything in this article is patently wrong, like the claim that &quot;[C++] only rudimentary concurrency mechanisms&quot;. C++ has a formally verified memory and execution model, which is the defacto industry standard, and a rich library of concurrency primitives.&lt;/p&gt;— Bryce Adelstein Lelbach (@blelbach) December 8, 2020&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;In C++, all references are nullable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In C++, &lt;em&gt;no&lt;/em&gt; references are nullable 😉.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#java--c&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;JAVA &amp;amp; C#&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;since the early versions of C# were a Microsoft implementation of Java&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C# was an imitation of Java. But it was a new language and never intended as an implementation of Java.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In particular, C# claims to support functional programming. I must disagree… What functional features should a language have? At the very least, built-in support for immutable data structures, pattern matching, pipe operator for function composition, Algebraic Datatypes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those are all great features, but none of them are the essence of functional programming.
The first functional language, Lisp, supports none of those features.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jfrech.com/blog/&quot; target=&quot;_blank&quot;&gt;Jonathan Frech&lt;span&gt;&lt;/span&gt;&lt;/a&gt; had a great comment about that some do not consider Lisp as a functional language.
That being said, even in &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_ML&quot; target=&quot;_blank&quot;&gt;Standard ML’97&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, a language probably considered more “functional” by some, there is no support for the pipe operator.
The standard library has only minimum support for persistent data structures (it didn’t even have an immutable map/dictionary type).
Lambda calculus, the holy grail of functional programming, also has none of the above mentioned features.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;By the way, C# does support pattern matching. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
The author seems to acknowledge this fact earlier and forget later,
again made me wonder whether some part of the post is “borrowed” from elsewhere.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;rudimentary concurrency support&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C# is the language that makes the async/await paradigm popular.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In C#, all references are nullable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Except that there are &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references&quot; target=&quot;_blank&quot;&gt;nullable-references&lt;span&gt;&lt;/span&gt;&lt;/a&gt; support and references can be made not-null by default.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#python&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Python&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Language family: C&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What does “The C family languages” even mean?
Languages share a syntax resemble C?
And how does Python suddenly become a C-family language?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Python is an interpreted language&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“Interpreted language” is a common buzzword in this field without a clear definition.
Instead of the language itself, a language implementation decides whether it is “interpreted” or “compiled.”
Plus, there are a lot of middle-ground between an ahead-of-time compiler and a tree-walk interpreter,
and most language implementations these days are in the middle ground.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Python is also pretty slow to start up&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A Python VM usually boots up in less than 100ms.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#rust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Rust&lt;/h2&gt;
&lt;p&gt;Rust also suffers from a lot of unfair ranting for its “low productivity” in this article, and to be honest all the criticism for Rust in this article looks like from a quick Google search.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The runtime performance of Rust programs is a little faster than Go.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can’t compare the runtime performance of programming languages without context like that.
There are a lot of performance design tradeoff,
and a language that runs faster in one circumstance is possible to run slower in another.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The first language on our list with a modern null alternative&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C++ has &lt;code&gt;std::optional&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and Java has &lt;code&gt;Optional&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Developers have to worry about things like boxing and pinning, which typically are done automatically in a garbage-collected language.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some garbage collectors move memories in a process called memory compaction,
and that is why C#, for example, also support pinning.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#typescript&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Typescript&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Even experimental features can be enabled in JavaScript with the use of Babel, which can’t be done for TypeScript.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Totally not true&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While JavaScript developers can use libraries that help with immutability, TypeScript developers typically have to rely on the native array/object spread operators&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Both immutable.js and Rambda, the Javascript libraries that the author mentioned, provide typescript type definitions, and they are not harder to use compared to using them in JS.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#functional-languages&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Functional languages&lt;/h2&gt;
&lt;p&gt;As a person who tries to promote functional languages,
the author should know better about those languages.
Unfortunately, the author seems to have more errors in those languages,
probably because they change from “opinionated rant mode” into actually talking about language features in this section.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#haskell&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Haskell&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;There’s no type system more powerful than Haskell.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No type system can be considered the most “powerful.”
By the way, what about dependent type languages &lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;?&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#ocaml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;OCaml&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;There’re three package managers — Opam, Dune, and Esy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dune is not a package manager, but instead a build system. It is often used in combination with Opam.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The go-to book for learning OCaml is Real World OCaml. The book hasn’t been updated since 2013, and many of the examples are outdated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href=&quot;http://dev.realworldocaml.org/&quot; target=&quot;_blank&quot;&gt;2nd edition&lt;span&gt;&lt;/span&gt;&lt;/a&gt; of &lt;em&gt;Real World OCaml&lt;/em&gt; is up-to-date and also available freely online.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Scala&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Scala has first-class support for immutable data structures (using case classes).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Scala standard library does provide fantastic support for immutable data structures.
However, case classes have nothing to do with those data structures.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#elm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Elm&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The only time when you will encounter runtime errors with Elm is when interacting with outside JavaScript code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately, the Elm compiler still can generate Javascript code that throws exceptions at runtime.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;interop with JavaScript libraries next to impossible&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are custom elements&lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and ports&lt;sup&gt;&lt;a href=&quot;#user-content-fn-6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This means that the developers have no access to the vast ecosystem of libraries and components made for React.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can make a React component a custom element.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We don’t even know whether or not he’s still working full-time on Elm. The language might actually be dead by now.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Evan is still doing work on Elm and interacts with the community regularly.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#reason-ml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Reason ML&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Just like TypeScript, ReasonML has access to the entire JavaScript ecosystem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using Javascript libraries in Reason requires some boilerplates (&lt;code&gt;external&lt;/code&gt;), just like in Elm.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;React initially was written in OCaml&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The first prototype of React was written in Standard ML, rather than OCaml.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#elixir&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Elixir&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Language family: ML.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, I can stand that you say Haskell or Elm is in the ML family (though I disagree), but what is a dynamic-typed language doing here?&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The article has some good content on pure functions, algebraic data types, pattern matching, and error-handling in FP languages.
If the author removes all the biased, incorrect, and misleading content, I would recommend it for people to read.
However, the author chooses a different path.
Unfortunately, the Internet always rewards clickbait and sensational articles these days instead of posts with meaningful content.&lt;/p&gt;
&lt;p&gt;Also, what worries me is that these kinds of blog posts will push people away from functional languages.
A minority of trolls make people lose faith in the whole community.
For example, here is one comment on Medium to the article:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ooh, you’re a functional programmer! That explains why I had that feeling you didn’t know what you were talking about.&lt;/p&gt;
&lt;p&gt;I can stop reading now. I read enough flawed examples, dubious comparisons and more from articles written by your kind.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Rest assured that most people in the functional programming community are friendly and don’t have that kind of bias against your favorite language.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching&quot; target=&quot;_blank&quot;&gt;https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/optional&quot; target=&quot;_blank&quot;&gt;https://en.cppreference.com/w/cpp/utility/optional&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html&quot; target=&quot;_blank&quot;&gt;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://babeljs.io/docs/en/babel-preset-typescript&quot; target=&quot;_blank&quot;&gt;https://babeljs.io/docs/en/babel-preset-typescript&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-4-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Dependent_type&quot; target=&quot;_blank&quot;&gt;https://en.wikipedia.org/wiki/Dependent_type&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://guide.elm-lang.org/interop/custom_elements.html&quot; target=&quot;_blank&quot;&gt;https://guide.elm-lang.org/interop/custom_elements.html&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Coding</category><category>FP</category><category>Opinion</category></item><item><title>Improve Rust Link Time with lld</title><link>https://lesleylai.info/en/improve-rust-link-time-with-lld</link><guid isPermaLink="true">https://lesleylai.info/en/improve-rust-link-time-with-lld</guid><description>This post talks about the issue of slow link time in Rust and how to improve it by switching the default linker to lld - the LLVM linker.</description><pubDate>Sun, 01 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Update 2025: Rust now uses &lt;code&gt;lld&lt;/code&gt; as the default linker &lt;a href=&quot;https://blog.rust-lang.org/2024/05/17/enabling-rust-lld-on-linux/&quot; target=&quot;_blank&quot;&gt;on x86-64 Linux in nightly&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Some Rust’s wasm and aarch64 targets also already use &lt;code&gt;lld&lt;/code&gt; by default.&lt;/strong&gt;&lt;/p&gt;
&lt;span&gt;&lt;p&gt;For faster iterative development, alternatives like &lt;a href=&quot;https://github.com/rui314/mold&quot; target=&quot;_blank&quot;&gt;mold&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/davidlattimore/wild&quot; target=&quot;_blank&quot;&gt;wild&lt;span&gt;&lt;/span&gt;&lt;/a&gt; are also worth considering.&lt;/p&gt;&lt;/span&gt;
&lt;p&gt;Today I start to experiment with the WebGPU API, and I choose to use the &lt;a href=&quot;https://github.com/gfx-rs/wgpu-rs&quot; target=&quot;_blank&quot;&gt;wgpu-rs&lt;span&gt;&lt;/span&gt;&lt;/a&gt; implementation in Rust.
I am happy with the experience overall, but one difficulty I met is the long iterative compilation time:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;img src=&quot;/_astro/compiling.DMTouufm_19qN58.webp&quot; alt=&quot;Code is compiling meme&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;262&quot; /&gt;&lt;figcaption&gt;&lt;p&gt;Compiling&lt;br /&gt;
Source: &lt;a href=&quot;https://xkcd.com/303/&quot;&gt;xkcd&lt;/a&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;blockquote&gt;&lt;p&gt;The compile-time of my webgpu project is ridiculously slow (about 10s for this single file), any #Rust expert know how to improve that?&lt;/p&gt;— Lesley Lai (@LesleyLai6) November 2, 2020&lt;/blockquote&gt;
&lt;p&gt;For some applications, slow compile-time is OK.
Coding some hard algorithms requires extensive thinking,
and if they compile and pass unit tests,
they are likely correct.&lt;/p&gt;
&lt;p&gt;By contrast, for graphics and game programming, iteration time is paramount.
A lot of the time, there are no right or wrong answer to a problem,
instead, we need to do a lot of small tweakings.&lt;/p&gt;
&lt;p&gt;Fortunately, a person (user Rukai) on the &lt;a href=&quot;https://discord.gg/6mgNGk7&quot; target=&quot;_blank&quot;&gt;Graphics Programming Discord&lt;span&gt;&lt;/span&gt;&lt;/a&gt; provides a solution.&lt;/p&gt;
&lt;p&gt;What I need to do is to create a config file &lt;code&gt;~/.cargo/config&lt;/code&gt; as&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;rustflags&lt;/span&gt;&lt;span&gt; = [&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;-C&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;link-arg=-fuse-ld=lld&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This flag sets &lt;code&gt;lld&lt;/code&gt; to the linker, which is way faster than Rust’s default linker.
And I also need to install &lt;code&gt;lld&lt;/code&gt; on my computer.&lt;/p&gt;
&lt;p&gt;And this simple change magically makes my iterative compilation time under 3s.
It is still not ideal from my perspective, but at least I can enjoy doing this project again.&lt;/p&gt;</content:encoded><category>Coding</category><category>Rust</category></item><item><title>Recursive Modules in OCaml</title><link>https://lesleylai.info/en/recursive_modules_in_ocaml</link><guid isPermaLink="true">https://lesleylai.info/en/recursive_modules_in_ocaml</guid><description>Recursive module is an interesting feature in OCaml. To use it, we need to use the form



Explicit signature is required when using recursive modules, as the compiler can no longer deduce the module signature with recursion.

A typical recursive module looks like the following:



And we can even h..</description><pubDate>Thu, 15 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recursive module is an interesting feature in OCaml.
To use it, we need to use the form&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rec&lt;/span&gt;&lt;span&gt; module-name : module-signature = module-expr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Explicit signature is required when using recursive modules,
as the compiler can no longer deduce the module signature with recursion.&lt;/p&gt;
&lt;p&gt;A typical recursive module looks like the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sig&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;(*&lt;/span&gt;&lt;span&gt; explicit signature &lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;(*&lt;/span&gt;&lt;span&gt; Implementations &lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And we can even have mutually recursive modules, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sig&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; ... &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sig&lt;/span&gt;&lt;span&gt; ... &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; ... &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;My primary use case of recursive modules is to combine with first-class modules.
First-class modules are ordinary values that wrap a module.
It is a powerful way to introduce dynamic polymorphism in OCaml.&lt;/p&gt;
&lt;p&gt;Dynamic polymorphism is usually combined with recursive data types,
but Ocaml modules are not recursive by default.
Thus, recursive modules serve as valuable additions.&lt;/p&gt;
&lt;p&gt;For example,
I use first-class modules and recursive modules in my &lt;a href=&quot;https://github.com/LesleyLai/ocamlpt&quot; target=&quot;_blank&quot;&gt;ocamlpt&lt;span&gt;&lt;/span&gt;&lt;/a&gt; project.
Ocamlpt is a path tracer,
where its scene contains different kinds of shapes.
The signature of a shape is the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sig&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ray&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;t &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Material&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;hit_record &lt;/span&gt;&lt;span&gt;option&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bounding_box&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Aabb&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We want to make the shape polymorphic, so we need to use first-class modules.
In the below code, I introduce a &lt;code&gt;Shape_instance&lt;/code&gt; modules that wrap both the shape module and the value of that module,
and I also add a &lt;code&gt;build_shape&lt;/code&gt; function that builds first-class modules of the signature of &lt;code&gt;Shape_instance&lt;/code&gt;.
This way, we can store those first-class modules, and Whenever we want to use them, we can unwrap the first-class modules to get a concrete &lt;code&gt;Shape_instance&lt;/code&gt; module.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape_instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sig&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build_shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;shape&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;module struct&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;module &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;end &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape_instance&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above code is good enough to deal with concrete shapes such as spheres or triangles.
However, the shapes are organized in a tree structure called
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bounding_volume_hierarchy&quot; target=&quot;_blank&quot;&gt;bounding volume hierarchy (BVH)&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
And each BVH node can contain other shapes, including BVH nodes themselves.&lt;/p&gt;
&lt;p&gt;We can implement the BVH node with recursive modules:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bvh_node&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sig&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape_instance&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;left&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape_instance&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;right&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape_instance&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aabb&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Aabb&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;(*&lt;/span&gt;&lt;span&gt; Other members of the Bvh_node module &lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;(*&lt;/span&gt;&lt;span&gt; Creating bvh code from a list of objects &lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;shapes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape_instance&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;span&gt;(*&lt;/span&gt;&lt;span&gt; if shapes contain 3 elements &lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;left&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;right&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aabb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Aabb&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;union left&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;aabb&lt;/span&gt;&lt;span&gt; right&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;aabb&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ left=(build_shape (&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bvh_node&lt;/span&gt;&lt;span&gt;) left);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;right=(build_shape (&lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Bvh_node&lt;/span&gt;&lt;span&gt;) right);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;aabb }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above code works like magic,
but the code would not compile without the &lt;code&gt;rec&lt;/code&gt; keyword before &lt;code&gt;Bvh_node&lt;/code&gt;,
since the &lt;code&gt;create&lt;/code&gt; function refers to the module &lt;code&gt;Bvh_node&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;All in all,
recursive modules is a way to support cyclic dependencies among components
that the purely hierarchical module systems cannot support.
Such cyclic dependencies are usually undesirable and can be avoided by changing the software design.
Nevertheless, sometimes there are legitimate reasons to have a module depend on itself,
especially consider how versatile the OCaml module system is.
In those cases, recursive modules can serve as a valuable asset.&lt;/p&gt;</content:encoded><category>Coding</category><category>OCaml</category></item><item><title>Beware passing mutable lambda to STL algorithms</title><link>https://lesleylai.info/en/mutable-lambda-in-algorithms</link><guid isPermaLink="true">https://lesleylai.info/en/mutable-lambda-in-algorithms</guid><description>Passing complex mutable lambdas to C++ STL algorithms often leads to code that&apos;s hard to read and maintain. This article argues against treating &apos;no raw-loop&apos; as dogma, and explores how using mutable lambdas undermine the benefits of &lt;algorithm&gt;. It also provides detailed case study on LeetCode&apos;s Two Sum and a predicate-based inner product.</description><pubDate>Wed, 30 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, I have seen some people passing complex mutable lambdas to standard algorithms.
Those usages usually come from one mindset:
“Since we want to follow ‘no raw-loop,’
and the choice of STL algorithms is limited,
what can we do other than using a mutable lambda to hold our complicated logic?”
I think that both premises of this thought are wrong.
First, “no raw-loop” should be treated as an ideal instead of dogma.
Second, even though STL algorithms cannot cover every use case,
we can always write algorithms to fit our needs.&lt;/p&gt;
&lt;p&gt;I expressed this thoughts in the following tweet:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Random thought: if you want to pass a complicated mutable lambda to a C++ standard algorithm, you are using the wrong algorithm.&lt;/p&gt;— Lesley Lai (@LesleyLai6) September 21, 2020&lt;/blockquote&gt;
&lt;p&gt;And this post tries to expend this thought a little bit.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#mutable-lambdas-destroy-the-beauty-of-algorithms&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Mutable Lambdas destroy the beauty of &lt;code&gt;&amp;lt;algorithms&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Why we use &lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt;? Is it because it is “elegant” or “modern?”
Or is it because “&lt;em&gt;Some experts said so&lt;/em&gt;?”
Both are horrible reasons to prefer &lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt; over loops.
For me,
&lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt; provides the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Less mutable states&lt;/li&gt;
&lt;li&gt;Declarative&lt;/li&gt;
&lt;li&gt;Express intent&lt;/li&gt;
&lt;li&gt;Known correct implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mutable lambda destroys all of them.
First, STL algorithms encapsulate mutable states into small functions.
Nevertheless, we only need &lt;em&gt;mutable&lt;/em&gt; lambda when our algorithm fails to encapsulate all mutable logics.
Second,
since the mutable states and complex control flow are back,
we can no longer call our implementation declarative.
Third,
since we need complicated logic inside a lambda to stretch the algorithm to perform our task,
the algorithm does not express our intent.
Fourth,
since the algorithm does not express our intent,
even though the algorithm itself is correct,
there can still be bugs lure in our own &lt;em&gt;hard-to-understand&lt;/em&gt; code.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#a-leetcode-example&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;A LeetCode example&lt;/h2&gt;
&lt;p&gt;Let’s look at the following C++ solution to the &lt;a href=&quot;https://leetcode.com/problems/two-sum/&quot; target=&quot;_blank&quot;&gt;LeetCode Two Sum problem&lt;span&gt;&lt;/span&gt;&lt;/a&gt; by Yacob Cohen-Arazi. The problem is worded as follows: “&lt;em&gt;Given an array of integers &lt;code&gt;nums&lt;/code&gt; and an integer &lt;code&gt;target&lt;/code&gt;, return indices of the two numbers such that they add up to target.&lt;/em&gt;” and LeetCode provides the type signature of the &lt;code&gt;twoSum&lt;/code&gt; function that we cannot change.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;twoSum&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nums&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; idx1{}, idx2{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process_and_lookup&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[m &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;unordered_map&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, target, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;idx1, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;idx2]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; item) &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; iter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(target &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; item);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (iter &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cend&lt;/span&gt;&lt;span&gt;(m)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;[item] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;idx1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;iter&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;idx2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; iter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;find_if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cbegin&lt;/span&gt;&lt;span&gt;(nums), &lt;/span&gt;&lt;span&gt;cend&lt;/span&gt;&lt;span&gt;(nums), process_and_lookup);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;assert&lt;/span&gt;&lt;span&gt;(iter &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cend&lt;/span&gt;&lt;span&gt;(nums));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {idx1, idx2};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This version is long, messy, and hard to read.
It also contains five mutable states &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;idx1&lt;/code&gt;, &lt;code&gt;idx2&lt;/code&gt;, &lt;code&gt;i&lt;/code&gt;, and &lt;code&gt;target&lt;/code&gt;,
even though &lt;code&gt;target&lt;/code&gt; is never modified.
Here is the loop version I wrote that are doing essentially the same logic:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;twoSum&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nums&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::unordered_map&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; nums_map;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; size &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;nums&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; size; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;i) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; item &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nums&lt;/span&gt;&lt;span&gt;[i];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; iter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nums_map&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(target &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; item);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (iter &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nums_map&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span&gt;iter&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;span&gt;, i};&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nums_map&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emplace&lt;/span&gt;&lt;span&gt;(item, i);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::runtime_error{&lt;/span&gt;&lt;span&gt;&quot;No solution exist&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This loop version is shorter, easier to understand, and only contains two mutable states: the map &lt;code&gt;nums_map&lt;/code&gt; and index &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt; version lands badly here because &lt;code&gt;std::find_if&lt;/code&gt; does not match this problem’s intent.
&lt;code&gt;std::find_if&lt;/code&gt; finds a &lt;em&gt;single&lt;/em&gt; element that matches a predicator,
but our situation requires to find two elements that match a predicator together.
As a result,
it does not provide enough useful functionalities for this problem
but instead serves as an obstacle.
I consider this kind of &lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt; usages instances of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstraction_inversion&quot; target=&quot;_blank&quot;&gt;abstraction inversion&lt;span&gt;&lt;/span&gt;&lt;/a&gt; anti-pattern,
where the abstraction is so unfit for the task that we start to re-implements the implementation details that our abstractions suppose to hideaway.
This kind of usage makes the code hard to read,
introduces potential non-trivial runtime cost,
and increases the possibility of introducing bugs.
The &lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt; header tries to address all of the adversities,
but by using mutable lambda,
we somehow land us in a situation worse than the loop counterparts of our functions.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#another-example-calculates-inner-product-until-it-satisfies-a-predicate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Another Example: Calculates inner product until it satisfies a predicate&lt;/h2&gt;
&lt;p&gt;Dima Savin gives me a tricky problem:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Ok, which algorithm should I use to calculate the inner product until it exceeds a value and get the index when it happened? Didn&apos;t find find just the right thing in a table by @code_report that doesn&apos;t require a mutable lambda.&lt;/p&gt;— Dima Savin (@dima_savin) September 21, 2020&lt;/blockquote&gt;
&lt;p&gt;This problem is tricky to solve with STL algorithms
since STL algorithms are designed to compose sequentially,
and as we will see in the loop version,
there is multiple interleaved logic during the iteration.&lt;/p&gt;
&lt;p&gt;Thus, I will use the loop version as the starting point.
Since Dima does not specify what happens if we didn’t find the index,
I return the final result of &lt;code&gt;i&lt;/code&gt;,
which should be the index of the last element plus one:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_iterator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_iterator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Itr2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inner_product_till&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Itr2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upper_bound&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T acc{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (; first1 &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; last1; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;first1, &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;first2, &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;i) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acc &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;move&lt;/span&gt;&lt;span&gt;(acc) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;first1 &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;first2;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (acc &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; upper_bound) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; i; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This version is certainly not ideal.
It contains four mutable states &lt;code&gt;first1&lt;/code&gt;, &lt;code&gt;first2&lt;/code&gt;, &lt;code&gt;i&lt;/code&gt;, and &lt;code&gt;acc&lt;/code&gt;.
Nevertheless,
the logic inside the loop is simple,
and every decent C++ programmers should be able to grasp this code
in a relatively short amount of time.&lt;/p&gt;
&lt;p&gt;I am satisfied with this version.
Even the person who proposed “no raw loop” ideology in the first place,
&lt;a href=&quot;https://sean-parent.stlab.cc/&quot; target=&quot;_blank&quot;&gt;Sean parent&lt;span&gt;&lt;/span&gt;&lt;/a&gt;,
will not consider this kind of simple loops that are nicely encapsulated in a function “raw loops.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A raw loop is any loop inside a function where the function serves purpose larger than the algorithm implemented by the loop — Sean Parent, 2013 &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;code&gt;std::find&lt;/code&gt; + mutable lambda version, however,
is certainly inferior to the loop version.
This version contains the same amount of mutable states,
and is signaficantly harder to read even for people familiar
with this kind of lambda-heavy style of programming:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_iterator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_iterator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Itr2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inner_product_till&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Itr2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upper_bound&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;find_if&lt;/span&gt;&lt;span&gt;(first1, last1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;acc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; T{}, &lt;/span&gt;&lt;span&gt;first2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;upper_bound&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;elem&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acc &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;move&lt;/span&gt;&lt;span&gt;(acc) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; elem &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;first2;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (acc &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; upper_bound) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;first2;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If we step back a little bit and think about what logic we try to achieve here.
We can find two interleaving steps.
First, we need to perform an inner product to the elements we meet so far.
Second, we find whether this calculated inner product is greater than the &lt;code&gt;upper_bound&lt;/code&gt;.
If we ignore the “interleaving” part,
then we can use &lt;code&gt;std::transform&lt;/code&gt; and &lt;code&gt;std::partial_sum&lt;/code&gt; to perform the first step and &lt;code&gt;std::find_if&lt;/code&gt; to perform the second step:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_iterator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_iterator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Itr2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inner_product_till&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Itr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Itr2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upper_bound&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; products;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;transform&lt;/span&gt;&lt;span&gt;(first1, last1, first2, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;back_inserter&lt;/span&gt;&lt;span&gt;(products),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::multiplies&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;{});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;partial_sum&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;find_if&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; e &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; upper_bound; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;distance&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;products&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(), result);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This version is the closest to my thought flow,
however, it is also very inefficient
since it allocates extra heap memory and eagerly computes results that we may not need.
Lazy ranges view solves the performance problem,
If ranges have numeric algorithms support,
then we can potentially write the following code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;input_range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Range&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inner_product_till&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upper_bound&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;size_t&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;ranges&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;distance&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;view&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;transform&lt;/span&gt;&lt;span&gt;(r1, r2, &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::multiplies&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;{})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;view&lt;/span&gt;&lt;span&gt;::partial_sum&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;view&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;take_while&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; e &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; upper_bound; }));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This version is splendid.
It does not allocate and exit early,
so in theory, it can be as efficient as the raw loop version or the mutable lambda version,
and it is certainly much more readable and less error-prone to write than both of them.
Unfortunately, none of the algorithms in the &lt;code&gt;&amp;lt;numeric&amp;gt;&lt;/code&gt; header is included in the C++20 ranges.
As a result, &lt;code&gt;std::view::partial_sum&lt;/code&gt; is not a thing at the time of this writing.
Nevertheless, the &lt;a href=&quot;https://github.com/ericniebler/range-v3&quot; target=&quot;_blank&quot;&gt;range-v3&lt;span&gt;&lt;/span&gt;&lt;/a&gt; library includes all those functionalities.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#dont-be-afraid-of-writing-your-own-algorithm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Don’t be afraid of writing your own algorithm&lt;/h2&gt;
&lt;p&gt;Another way to solve this problem is to write your own STL-style algorithm.
For example, in the above example,
we can write our own &lt;code&gt;view::partial_sum&lt;/code&gt; view adapter.&lt;/p&gt;
&lt;p&gt;Our algorithm often does not need to be very generic in practice,
as you can always enhance it later when you need to reuse this piece of code.
The starting point of an algorithm can merely be “extracting a loop into a function.”&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Writing your own algorithm is not rocket science, but the more generic an algorithm is, the more factors we need to consider. &lt;a href=&quot;https://www.elbeno.com/blog/&quot; target=&quot;_blank&quot;&gt;Ben Deane&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s talk &lt;a href=&quot;https://www.youtube.com/watch?v=InMh3JxbiTs&quot; target=&quot;_blank&quot;&gt;Constructing Generic Algorithms: Principles and Practice&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an excellent resource on this topic.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Also, the interesting thing is that
the above &lt;code&gt;inner_product_till&lt;/code&gt; is an STL-compatible algorithm.
And we can treat it as one of the lowest levels of abstraction.
If it is well tested, fast, and well behaved, who cares about whether it uses loops or other algorithms under-the-hood?
It is not as generic as &lt;code&gt;std::inner_product&lt;/code&gt;,
but we can always add initial value and the plus/multiply binary operations as parameters later if we need them.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#what-about-using-mutable-lambdas-in-stdgenerate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;What about using mutable lambdas in &lt;code&gt;std::generate&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;A lot of usages of &lt;code&gt;std::generate&lt;/code&gt; use mutable lambdas as a “generator” function.
For example, the following code generates the first 20 numbers of
the recurrence relationship .&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;This recurrence relationship has a simple close form ,
though in more complicated problems,
using mutables may be necessary.&lt;/p&gt;
&lt;/aside&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;seq&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;generate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(seq), &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(seq),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]() &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;exchange&lt;/span&gt;&lt;span&gt;(x, x &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This kind of “generator” usage of &lt;code&gt;std::generate&lt;/code&gt; and mutable lambdas is common,
and I think, unlike previous examples, they are fine.&lt;/p&gt;
&lt;p&gt;There is an advantage of this version compared to using a loop.
Compared to the equivalent loop version,
the scope of the mutable variable &lt;code&gt;x&lt;/code&gt; is constrained to be in lambda’s scope.
And we should strive to make the scope of variables (especially mutable) as small as possible.
Nevertheless, we can surround the loop with explicit brace pair to get a similar effect:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;seq&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; elem: seq) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;elem &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;exchange&lt;/span&gt;&lt;span&gt;(x, x &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#consider-the-alternatives-over-passing-mutable-lambdas-to-stl-algorithms&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Consider the alternatives over passing mutable lambdas to STL algorithms&lt;/h2&gt;
&lt;p&gt;To sum everything up, I believe passing mutable lambdas to STL algorithms other than &lt;code&gt;std::generate&lt;/code&gt; or &lt;code&gt;std::generate_n&lt;/code&gt; is an anti-pattern that we should try to avoid. There are several alternatives. Sometimes we can switch to a better algorithm. Sometimes using a plain-old loop is the better option. And sometimes, we can write our customized algorithms to achieve the task.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Sean Parent, 2013. C++ Seasoning. Retrieved September 23, 2020, from &lt;a href=&quot;http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning&quot; target=&quot;_blank&quot;&gt;http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>C++</category><category>Coding</category><category>Opinion</category></item><item><title>The implication of const or reference member variables in C++</title><link>https://lesleylai.info/en/const-and-reference-member-variables</link><guid isPermaLink="true">https://lesleylai.info/en/const-and-reference-member-variables</guid><description>In the conventional wisdom of the C++ community, non-static const or reference data variables are considered problematic. Surprisingly, I cannot find a single resource dedicated to this topic.

I decide to write this post because the same problem raises several time by different people on Twitter an..</description><pubDate>Tue, 18 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the conventional wisdom of the C++ community,
non-static &lt;code&gt;const&lt;/code&gt; or reference data variables are considered problematic.
Surprisingly, I cannot find a single resource dedicated to this topic.&lt;/p&gt;
&lt;p&gt;I decide to write this post because the same problem raises several time by different people on Twitter and the &lt;a href=&quot;https://discord.com/invite/ZPErMGW&quot; target=&quot;_blank&quot;&gt;#include ＜C++＞ discord server&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
There are solid reasons on why you should avoid &lt;code&gt;const&lt;/code&gt; or reference member variables in C++.
Nevertheless, like many things in C++, “avoid” does not mean “never use.”
And they can occasionally still find some uses.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#const-members&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Const members&lt;/h2&gt;
&lt;p&gt;If you are familiar with any programming languages, such as Rust, that treat &lt;code&gt;const&lt;/code&gt; as default and mutable as second class citizens, you may have the temptation to mark everything &lt;code&gt;const&lt;/code&gt; if you don’t need to modify them.
This practice provides a lot of benifits even in C++, as countless &lt;a href=&quot;https://bsky.app/profile/lefticus.bsky.social&quot; target=&quot;_blank&quot;&gt;Jason Turner&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://bsky.app/profile/gregcons.bsky.social&quot; target=&quot;_blank&quot;&gt;Kate Gregory&lt;span&gt;&lt;/span&gt;&lt;/a&gt; talks show.
Alas, in C++, every best practice has a twist, such as “&lt;code&gt;const&lt;/code&gt; everything &lt;em&gt;except&lt;/em&gt; member variables.”&lt;/p&gt;
&lt;p&gt;&lt;code&gt;const&lt;/code&gt; member variables disables &lt;em&gt;assignment&lt;/em&gt; and &lt;em&gt;move semantics&lt;/em&gt; for a class.
For assignments, it makes sense, since how can you assign something to a constant?
For move semantics, even though technically copy is a valid move implementation, the type system cannot guarantee that the after-move state remains the same.&lt;/p&gt;
&lt;p&gt;“What is the big deal? I already said that I don’t want to mutate the fields ever.” you may ask.&lt;/p&gt;
&lt;p&gt;Except that &lt;code&gt;swap&lt;/code&gt; uses both &lt;em&gt;assignment&lt;/em&gt; and &lt;em&gt;move semantics&lt;/em&gt;.
Without move operations, every move fallback to a copy.
The lack of assignment is more severe,
as it makes &lt;code&gt;swap&lt;/code&gt; fail to compile:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BadImmutablePoint&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BadImmutablePoint p1;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BadImmutablePoint p2 {&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;55&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;swap&lt;/span&gt;&lt;span&gt;(p1, p2);&lt;/span&gt;&lt;span&gt; // Error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;That also means no to all STL facilities that use assignments internally.
For example, &lt;code&gt;std::sort&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;BadImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; points;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Sort by x-axis&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;ranges&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(points, {}, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;BadImmutablePoint&lt;/span&gt;&lt;span&gt;::x);&lt;/span&gt;&lt;span&gt; // Error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#but-i-dont-want-to-mutate-the-member-variable&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;But I don’t want to mutate the member variable!&lt;/h2&gt;
&lt;p&gt;The best thing you can do in C++ is to make the member variable &lt;code&gt;private&lt;/code&gt; and only expose the getter.
Access control still doesn’t prevent the class internals from modifying the members, but at least now everything outside the class can’t.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x_ &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; y_ &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) : &lt;/span&gt;&lt;span&gt;x_&lt;/span&gt;&lt;span&gt;{x}, &lt;/span&gt;&lt;span&gt;y_&lt;/span&gt;&lt;span&gt;{y} {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; y_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; points;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;ranges&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(points, {}, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;::x);&lt;/span&gt;&lt;span&gt; // Ok&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;Notice that this line of sorting by getter is exactly the same as the sorting by member variable above.
C++20 ranges projection is a great feature.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;It is quite a bit of boilerplate.
And to be honest, I will stick with aggregate with none-constant fields in this particular case.
When you create a point variable, you can still mark the whole point as &lt;code&gt;const&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Point&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; Point immutable_point {&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;55&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If you want to get &lt;em&gt;really&lt;/em&gt; fancy, you can even create a small template to automate the process of only exposing getters.
Though I myself will certainly not go this far.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;typename&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const_wrapper&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T val_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const_wrapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt;) : &lt;/span&gt;&lt;span&gt;val_&lt;/span&gt;&lt;span&gt;{val} {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const_wrapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt;) : &lt;/span&gt;&lt;span&gt;val_&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;move&lt;/span&gt;&lt;span&gt;(val)} {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; T&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; val_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; val_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;Making this &lt;code&gt;const_wrapper&lt;/code&gt; class template more useful,
for example, by adding a variadic template constructor with type constraint,
is an exercise left for readers who really want to use this class 😉.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Then you can use this template as following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const_wrapper&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const_wrapper&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; points;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;ranges&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(points, {}, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;::x);&lt;/span&gt;&lt;span&gt; // Ok&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#reference-member-variables&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Reference member variables&lt;/h2&gt;
&lt;p&gt;Unlike pointers or “references” in a lot of other programming languages such as Java and Python,
C++ references cannot rebind.
Hence, we have a situation very similar to &lt;code&gt;const&lt;/code&gt; members.
A good analogy of references is a &lt;code&gt;const&lt;/code&gt; pointer that cannot be null.
For example, the below &lt;code&gt;struct&lt;/code&gt; subjects to the same problem of the &lt;code&gt;struct&lt;/code&gt; with &lt;code&gt;const&lt;/code&gt; fields.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BadImmutableTriangle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; a;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; b;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; c;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Like the solutions for const data members,
instead of storing a reference data member,
we can store a pointer member and only expose a reference getter.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutableTriangle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; a_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; b_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; c_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// No default constructor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutableTriangle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;a_&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;a}, &lt;/span&gt;&lt;span&gt;b_&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;b}, &lt;/span&gt;&lt;span&gt;c_&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;c} {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;a_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;b_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;constexpr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;c_; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The C++ standard library ships a &lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;std::reference_wrapper&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; helper template and it function a lot like our &lt;code&gt;const_wrapper&lt;/code&gt; above.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ImmutableTriangle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::reference_wrapper&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; a;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::reference_wrapper&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; b;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::reference_wrapper&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; c;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;std::reference_wrapper&lt;/code&gt; is more useful than my &lt;code&gt;const_wrapper&lt;/code&gt;.
As it is essential when we try to store something in the container while still maintains reference semantics:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt; triangles1;&lt;/span&gt;&lt;span&gt; // Error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::reference_wrapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; triangles2;&lt;/span&gt;&lt;span&gt; // Ok&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ImmutablePoint&lt;/span&gt;&lt;span&gt;*&amp;gt;&lt;/span&gt;&lt;span&gt; triangles3;&lt;/span&gt;&lt;span&gt; // Ok， with caveat&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The code &lt;code&gt;std::ranges::sort(triangles2);&lt;/code&gt; sorts &lt;code&gt;triangles2&lt;/code&gt; according to value comparisons.
And it will fail to compile if you haven’t define relevant comparison operators.
This is the desirable behavior, as there are no clear default ordering for triangles.
On the other hand, &lt;code&gt;std::ranges::sort(triangles3)&lt;/code&gt; compiles,
but it sorts by the addresses of pointers.
And this kind of nondetermistic behavior is undesirable.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#where-const-or-reference-member-variables-can-still-be-useful&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Where &lt;code&gt;const&lt;/code&gt; or reference member variables can still be useful&lt;/h2&gt;
&lt;p&gt;In some cases,
you already disabled the assignment and move operations, or you need to write your own anyway.
One of the primary examples is inheritance hierarchies.
And in those cases, it is fine to use &lt;code&gt;const&lt;/code&gt; or reference member variables.&lt;/p&gt;
&lt;p&gt;Another use case of &lt;code&gt;const&lt;/code&gt; or reference members is in local function objects,
where you don’t care about assignment behavior.
For example, variables captured by reference in a lambda expression
are desugared into reference member variables.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;C++, at its core, is an imperative language built on C heritage, and &lt;code&gt;const&lt;/code&gt; and references are afterthought of the language.
Also, The core language mechanisms heavily rely on assignment. Like it or not, when writing C++ classes, restricting user’s freedom to mutate member variables is not well supported.&lt;/p&gt;</content:encoded><category>Coding</category><category>C++</category></item><item><title>Zero is the Devil: Common ways to construct bogus proofs</title><link>https://lesleylai.info/en/zero-is-the-devil</link><guid isPermaLink="true">https://lesleylai.info/en/zero-is-the-devil</guid><description>It is easy to make mistakes when conducting mathematical proofs. Nevertheless, you can find some recurring error patterns in those proofs. And some of the most common reasons are related to the innocuous-looking number zero.


DIVISION-BY-ZERO FUN

Let’s look at the following “proof” of :

What is w..</description><pubDate>Sun, 10 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It is easy to make mistakes when conducting mathematical proofs.
Nevertheless, you can find some recurring error patterns in those proofs.
And some of the most common reasons are related to the innocuous-looking number zero.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#division-by-zero-fun&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Division-by-zero fun&lt;/h2&gt;
&lt;p&gt;Let’s look at the following “proof” of :&lt;/p&gt;

&lt;p&gt;What is wrong here?
We cancel both side of the equation by , but our premise includes ,
so we have a division-by-zero problem.&lt;/p&gt;
&lt;p&gt;Generally, performing cancellation without a zero-check is a terrible idea and should be avoided.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#sets-with-zero-elements&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Sets with zero elements&lt;/h2&gt;
&lt;p&gt;Ok, here is another stupid “proof” of that “all objects are the same.” We will assume that objects are countable.&lt;/p&gt;
&lt;p&gt;Proof:&lt;/p&gt;
&lt;p&gt;Let  be the set of all objects.
And let the property  mean that all subsets of  of size at most  contain the same same objects.
Formally:&lt;/p&gt;

&lt;p&gt;where  is the power set of the set , which is defined by all subsets of , and  means the cardinality (elements count) of .&lt;/p&gt;
&lt;aside&gt;
Pause for a moment and understand what this definition means, as we will use it in the following &quot;proof.&quot;
&lt;/aside&gt;
&lt;p&gt;We want to prove that . And we will prove that by mathematical induction on .&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Base case ():&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is trivial as the singleton set of object can only contain the same object.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inductive cases:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We treat  as our inductive hypothesis, and we need to prove .
Without the loss of generality,
pick an arbitrary set  such that .
Pick two objects , and let’s show .
Let  and .
Since , we know that  and  by the inductive hypothesis.
Pick an arbitrary object .
We get  because of  and .
Similarly, .
Thus, ,
which proves the inductive steps and the “theorem” .&lt;/p&gt;
&lt;p&gt;Again the mistake here is related to zero.
 can well be zero, so we cannot just “pick” an element from it.&lt;/p&gt;
&lt;p&gt;If you are from a more programming background,
it is no coincidence that dividing by zero or getting an element from a collection of zero-elements will cause horrible run-time errors.&lt;/p&gt;
&lt;aside&gt;
And most type systems will not save you (except dependent-typed ones, which have their own limitations.)
&lt;/aside&gt;
&lt;p&gt;I hope you have fun reading this post, just as me having fun writing it.&lt;/p&gt;</content:encoded><category>Math</category><category>Logic</category></item><item><title>The surprising codegen impact of noexcept</title><link>https://lesleylai.info/en/noexcept-codegen</link><guid isPermaLink="true">https://lesleylai.info/en/noexcept-codegen</guid><description>Would spamming the noexcept keyword make your C++ code faster? Sometimes. But not always. This post talks about the suprising downside when adding noexcept to functions.</description><pubDate>Mon, 02 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Would spamming the &lt;code&gt;noexcept&lt;/code&gt; keyword make your code faster? Sometimes. But not always. Consider the following snippet of code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I intentionally do not define &lt;code&gt;g&lt;/code&gt; in this translation unit since otherwise, the compiler will be too smart and inline everything.
Nevertheless, all the major C++ compilers can figure out that &lt;code&gt;f&lt;/code&gt; only contains a tail-call to &lt;code&gt;g&lt;/code&gt; and generate codes like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;jmp&lt;/span&gt;&lt;span&gt;     g()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now lets consider the following code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Since the compilers have no idea if &lt;code&gt;g&lt;/code&gt; would throw or not, they are forced to generate codes that invoke &lt;code&gt;std::terminate&lt;/code&gt; in case bad things happened.
Here is the result codegen from various compilers:&lt;/p&gt;
&lt;p&gt;msvc&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ip2state$int f(void) &lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;02H&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;08H&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;00H&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$cppxdata$int f(void) &lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;060H&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;DD&lt;/span&gt;&lt;span&gt;      imagerel $ip2state$int f(void)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; f(void) PROC                                      &lt;/span&gt;&lt;span&gt;; f, COMDAT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$LN5:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;rsp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;span&gt;                             &lt;/span&gt;&lt;span&gt;; 00000028H&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; g(void)                         &lt;/span&gt;&lt;span&gt;; g&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;npad    &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;rsp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;span&gt;                             &lt;/span&gt;&lt;span&gt;; 00000028H&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ret&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; f(void) ENDP                                      &lt;/span&gt;&lt;span&gt;; f&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;gcc&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;rsp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;    g()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;rsp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ret&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;clang&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;rax&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;    g()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pop&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;rcx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ret&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mov&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;rdi&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;rax&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;    __clang_call_terminate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;__clang_call_terminate:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;rax&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;    __cxa_begin_catch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::terminate()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#how-to-deal-with-c-functions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;How to deal with C functions?&lt;/h2&gt;
&lt;p&gt;Now we know that &lt;code&gt;noexcept&lt;/code&gt; can cause overhead if we call a non-noexcept function inside, how do we deal with functions that will not throw but are not mark as &lt;code&gt;noexcept&lt;/code&gt;? Fortunately, the venerable &lt;a href=&quot;https://bsky.app/profile/hanicka.net&quot; target=&quot;_blank&quot;&gt;Hana Dusíková&lt;span&gt;&lt;/span&gt;&lt;/a&gt; came up with a clever solution:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Did you ever get an suboptimal code, because you were calling external C function in your noexcept code?&lt;br /&gt;&lt;br /&gt;Suffer no more: &lt;a href=&quot;https://compiler-explorer.com/z/zyyAeW&quot;&gt;https://compiler-explorer.com/z/zyyAeW&lt;/a&gt;&lt;/p&gt;— Hana Dusíková 🍊 (@hankadusikova) June 27, 2020&lt;/blockquote&gt;
&lt;p&gt;You can mark the &lt;code&gt;noexcept_cast&lt;/code&gt; function force inline by compiler-specific extensions so it will not decrease performance in debug mode.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Don’t spam &lt;code&gt;noexcept&lt;/code&gt; if you don’t have a project-wise “no exception” policy. And be especially careful with higher-order functions that may invoke user-defined functions. All in all, &lt;code&gt;noexcept&lt;/code&gt; is a part of the type system and the contract of your API. Only add &lt;code&gt;noexcept&lt;/code&gt; to function that you want to guarantee not to throw.&lt;/p&gt;</content:encoded><category>Coding</category><category>C++</category></item><item><title>Concepts in Programming Languages, Part II: Statics</title><link>https://lesleylai.info/en/statics</link><guid isPermaLink="true">https://lesleylai.info/en/statics</guid><description>What are the statics of a programming language? Most programming languages exhibit a phase distinction between static and dynamic phase of processing. People sometime loosey say static of a language happened at “compile-time,” and dynamic of a language occurred at “run-time.” The static phase of a l..</description><pubDate>Mon, 02 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What are the &lt;em&gt;statics&lt;/em&gt; of a programming language?
Most programming languages exhibit a &lt;em&gt;phase distinction&lt;/em&gt; between &lt;em&gt;static&lt;/em&gt; and &lt;em&gt;dynamic&lt;/em&gt; phase of processing.
People sometime loosey say &lt;em&gt;static&lt;/em&gt; of a language happened at “compile-time,” and &lt;em&gt;dynamic&lt;/em&gt; of a language occurred at “run-time.”
The static phase of a language contains lexing, parsing, and in the case of static-typed languages, type-checking, and name resolution.
And the dynamic phase consists of the execution of a program.
We will only focus on static-typed languages in this post since the statics of dynamically-typed languages are trivial.&lt;/p&gt;
&lt;p&gt;In the static phase, we consider what the valid operations of a program are.
We construct a set of rules on the &lt;em&gt;typing judgments&lt;/em&gt; to state if an expression is well-formed for certain types.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#static-of-a-small-expression-language&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Static of a small expression language&lt;/h2&gt;
&lt;p&gt;Let’s consider a pretty dull expression-oriented language below.&lt;/p&gt;

&lt;p&gt;The above grammar defined two sorts,  and .
A type in this language can either be number or string.
Now it’s time to define the inference rules for the derivation of each operation.
First, the type of literals are quite obvious&lt;/p&gt;


&lt;p&gt;The we can define typing for operations of the language:&lt;/p&gt;

&lt;p&gt;If both the left-hand  side and the right-hand  side have the type ,
the expression  have the type .
Otherwise,  is ill-formed.&lt;/p&gt;
&lt;p&gt;We can use the similar way to define the rest of the operations:&lt;/p&gt;



&lt;p&gt;With those basic rules, we can state that in our language,  is well formed and  is a type error.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#typing-context&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Typing context&lt;/h2&gt;
&lt;p&gt;So far, our little language does not have variables.
In real programming languages, the type system needs to consider the typing context.
Let’s introduce variables and let binding into our language:&lt;/p&gt;

&lt;p&gt;Now we can define variable in our languages such as .
In a concrete syntax, the expression looks like&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let x = 1;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x + 2 // evaluates to 3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Whether  make sense depends on whether the variable x is defined in the surrounding context,
but our inference rule for  cannot catch that yet.&lt;/p&gt;
&lt;p&gt;What you can do is to introduce another concept called typing context , which is a mapping from variables to types.&lt;/p&gt;

&lt;p&gt;We inductively define  as either an empty set or the extension of another typing context  with one mapping from a variable to a type.&lt;/p&gt;
&lt;p&gt;Then you need to change the judgment form of typing to , which means “under typing context , the type of expression  is .”&lt;/p&gt;
&lt;p&gt;For most of the rules, nothing exciting happens besides the additional typing context in all judgments.&lt;/p&gt;






&lt;p&gt;For variable name resolution, we need to lookup in the typing context.&lt;/p&gt;

&lt;p&gt;For let bindings, we can extend the typing context and check the inference rules recursively.&lt;/p&gt;

&lt;p&gt;If you want to prevent name shadowing, you can change the rule a little bit.&lt;/p&gt;
</content:encoded><category>PLT</category></item><item><title>Concepts in Programming Languages, Part I: Judgements and Inference Rules</title><link>https://lesleylai.info/en/judgement-inference-rules</link><guid isPermaLink="true">https://lesleylai.info/en/judgement-inference-rules</guid><description>From a layperson’s perspective, the field of programming language research is full of jargon, greek letters, and weird symbols. On the one hand, Those common parlances make the programming language papers concise. On the other hand, you need not only mathematical maturity but also domain knowledge t..</description><pubDate>Sun, 26 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;From a layperson’s perspective, the field of programming language research is full of jargon, greek letters, and weird symbols.
On the one hand, Those common parlances make the programming language papers concise.
On the other hand, you need not only mathematical maturity but also domain knowledge to understand them.&lt;/p&gt;
&lt;p&gt;Since I am taking a &lt;a href=&quot;https://csci5535.cs.colorado.edu/s20/&quot; target=&quot;_blank&quot;&gt;Fundamentals of Programming Languages&lt;span&gt;&lt;/span&gt;&lt;/a&gt; course,
I want to share the key concepts I learned in a series of blog posts.
And I hope to write them in a “mortal-understandable” way to unravel the mysterious field of programming languages.&lt;/p&gt;
&lt;p&gt;I want to thank &lt;a href=&quot;https://www.cs.colorado.edu/~bec/&quot; target=&quot;_blank&quot;&gt;Professor Chang&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for offering this fantastic course,
and my classmates for creating a vibrant discussion environment.
I also need to make a disclaimer that many ideas of those posts come from the classroom.
I would cite writing texts when apply, but it is impossible to cite in class discussions.
Of course, all errors are my own, and please contact me for anything wrong.&lt;/p&gt;
&lt;p&gt;A lot of the mathematical concepts in the programming language field comes from the branch of &lt;a href=&quot;https://en.wikipedia.org/wiki/Propositional_calculus&quot; target=&quot;_blank&quot;&gt;propositional logic&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Thus, this first post focuses on the formal language of &lt;em&gt;Judgements&lt;/em&gt;, and &lt;em&gt;Inference Rules&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#judgements&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Judgements&lt;/h2&gt;
&lt;p&gt;A judgment is a statement or an assertion on a given abstract syntax tree.
Below are some standard notations we use for the judgments &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;Notice in the above examples such as ,
 is an unknown variable.
We call those &lt;em&gt;judgement forms&lt;/em&gt;
And we can plug in actual values into the variables of judgement forms to get a &lt;em&gt;judgement&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;As we can see, judgments can either be true or false.
You can consider it is a function application that returns a &lt;code&gt;bool&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#inference-rules&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Inference Rules&lt;/h2&gt;
&lt;p&gt;Inference rules are a logic form that takes premises and returns conclusions.
They generally have the standard form of the following:&lt;/p&gt;

&lt;p&gt;You can read them as “if all the premises are satisfied, then the conclusion.”&lt;/p&gt;
&lt;p&gt;Let’s inductively define the natural numbers by the inference rules.&lt;/p&gt;


&lt;p&gt;In this inference rule, we state that a natural number is either zero
or a succession of another natural number.
A rule without any premise, such as the first one, is called an &lt;em&gt;axiom&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Because using inference rule to describe syntax is verbose,
a common way to describe syntax is by &lt;a href=&quot;https://en.wikipedia.org/wiki/Context-free_grammar&quot; target=&quot;_blank&quot;&gt;grammar&lt;span&gt;&lt;/span&gt;&lt;/a&gt; notation
like the &lt;a href=&quot;https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form&quot; target=&quot;_blank&quot;&gt;Backus normal form&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (BNF).
A grammar of a programming language is a set of inductively defined &lt;em&gt;terms&lt;/em&gt;.
For example, for natural numbers, we can describe them as&lt;/p&gt;

&lt;p&gt;However, inference rules can express much more than syntax. For example, let’s define the semantics of the  operator of the natural number:&lt;/p&gt;


&lt;p&gt;We can define more operations, such as  and , by the inference rule.
Let’s look at another example, a singly linked-list of natural numbers:&lt;/p&gt;

&lt;p&gt;This grammar means that a  is either  or a -cell of natural number and another .
A  is an empty list, and a  is a “node” of the singly linked-list that contains an individual element and points to a sub-list.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;The convention of using the word “cons” comes from the programming language &lt;a href=&quot;https://en.wikipedia.org/wiki/Lisp_programming_language&quot; target=&quot;_blank&quot;&gt;Lisp&lt;span&gt;&lt;/span&gt;&lt;/a&gt;,
where &lt;code&gt;cons&lt;/code&gt; can be interpreted as “construct” or “constructor.”
&lt;code&gt;cons&lt;/code&gt; in Lisp is much more flexible than our definition because of the dynamic-typing nature of the language.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Now we can start to define operations on  with inference rules.
For example, we can define a &lt;code&gt;head&lt;/code&gt; function that gets the first element of the list:&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;#partial-function-total-function-and-error-handling&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Partial Function, Total Function, and Error handling&lt;/h3&gt;
&lt;p&gt;Notice our version of &lt;code&gt;head&lt;/code&gt; is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Partial_function&quot; target=&quot;_blank&quot;&gt;partial function&lt;span&gt;&lt;/span&gt;&lt;/a&gt;,
which means not all the list has a mapping to a natural number through &lt;code&gt;head&lt;/code&gt;.
In this particular case, we have not defined the meaning of &lt;code&gt;head(Nil)&lt;/code&gt;.
We have several choices of dealing with such partial functions,
one is to leave the operation as &lt;a href=&quot;https://en.wikipedia.org/wiki/Undefined_behavior&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;undefined&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.
This approach is what the C programming language takes, and it is the best for optimization,
though it impairs the &lt;a href=&quot;https://en.wikipedia.org/wiki/Type_safety&quot; target=&quot;_blank&quot;&gt;type safety&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another approach is to make such a function call “error” or “exception” such as&lt;/p&gt;

&lt;p&gt;And a third approach is to transform this operation to a total function:&lt;/p&gt;


&lt;p&gt;A lot of the modern programming language becomes eclectic on error-handling strategies.
For example, the &lt;a href=&quot;https://www.rust-lang.org/&quot; target=&quot;_blank&quot;&gt;Rust&lt;span&gt;&lt;/span&gt;&lt;/a&gt; programming language offers all three approaches in different contexts.
For certain operations, it not only offers a default “safe” version either with the second approach (&lt;code&gt;panic&lt;/code&gt;) or the third approach (&lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt;),
but also an “unsafe” version with the first approach.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#derivation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Derivation&lt;/h2&gt;
&lt;p&gt;You can easily create nonsense such as ,
so how to prove a judgment is correct?
To prove a judgment, you write &lt;em&gt;derivation&lt;/em&gt; (also called &lt;em&gt;derivation tree&lt;/em&gt; or &lt;em&gt;proof tree&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;A derivation always starts from axioms and ends at the judgment we want to prove.
For each step, we apply an inference rule to the previous judgment (s).&lt;/p&gt;
&lt;p&gt;For example, to prove “1 + 1 = 2” with our definition of nat, we have&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Derivation of 1 + 1 = 2&quot; loading=&quot;lazy&quot; width=&quot;977&quot; height=&quot;185&quot; src=&quot;/_astro/derivation1.DH8d33Im_Z1M9q8x.webp&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Reading from bottom to top, you can find that the derivation is analogous of the execution of a program:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Succ(Zero) + Succ(Zero)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= Zero + Succ(Succ(Zero))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= Succ(Succ(Zero))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We can trace the execution of the &lt;code&gt;+&lt;/code&gt; operation by substitution easily because it is a &lt;em&gt;pure function&lt;/em&gt;.
In other words, &lt;code&gt;+&lt;/code&gt; is deterministic and side-effect free, at least at the level that we concern.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;If you consider the &lt;em&gt;implementation details&lt;/em&gt; such as the mutation of registers and stack memory,
then there is no pure function,
although that does not help with our discussion.
A certain level of abstraction not only helps you,
but also the compilers to optimize for pure functions.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2&gt;&lt;a href=&quot;#analogy-to-programming&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Analogy to programming&lt;/h2&gt;
&lt;p&gt;All of the mathematical notations that we talked about have programming counterparts.
Below is a table comparison between math notation and programming:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Mathematical Notation&lt;/th&gt;&lt;th&gt;Implementation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Judgement form&lt;/td&gt;&lt;td&gt;A function signature of a function that returns &lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Judgement&lt;/td&gt;&lt;td&gt;Function application&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Inference Rules&lt;/td&gt;&lt;td&gt;Function body&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Derivation&lt;/td&gt;&lt;td&gt;Evaluation/Execution&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Let’s say that we have the judgement form , we can write it as a function signature&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; nat &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; option&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;nat&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;) -&amp;gt; bool&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The inference rule of &lt;code&gt;head&lt;/code&gt; can be view as the function body.&lt;/p&gt;


&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; nat &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; option&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;nat&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;) =&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;match &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; [] &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; hd&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; hd &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; e&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And the judgement such as  is analogous to function application such as&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;head Cons(Succ(Zero), Nil) Succ(Zero)  &lt;/span&gt;&lt;span&gt;&lt;span&gt;(*&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;*)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I use &lt;a href=&quot;https://ocaml.org/&quot; target=&quot;_blank&quot;&gt;OCaml&lt;span&gt;&lt;/span&gt;&lt;/a&gt; syntax as an example, but it applies to any programming languages.
The advantage of an ML-family language such as OCaml in my use case is there excellent support for inductively defined types such as &lt;code&gt;nat&lt;/code&gt; and &lt;code&gt;list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Notice that the literal translation from math generates very inefficient implementations.
In an actual implementation, You would probably write the &lt;code&gt;head&lt;/code&gt; function as:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;head&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; nat &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;match&lt;/span&gt;&lt;span&gt; l &lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hd&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Some&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;hd&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Nevertheless, it is still useful conceptually to see the connection between the mathematical notation and the actual programming.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#type-error-in-judgements&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;”Type error” in judgements&lt;/h3&gt;
&lt;p&gt;It is easy to make “type error” when writing judgments and inference rules.
For example, the following inference rule is incorrect as &lt;code&gt;+&lt;/code&gt; is not a natural number, so we cannot put it inside a &lt;code&gt;Succ&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is equally easy to make this kind of mistake when coding a tree-walking interpreter by mixing the abstract syntax and the values.
If you are using a statically-typed language, the type-checker will catch those kinds of errors.
On the contrary, when writing judgment and inference rules, you are on your own,
so building a mental “type checker” helps tremendously in writing judgments correctly.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#summary&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Judgments and inference rules are the fundamental building block of the formal definition of programming languages,
and it is hard to find a programming language paper without them.
Thus, it is crucial to understand how to read and write in such notations.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Robert Harper. &lt;em&gt;Practical Foundations for Programming Languages&lt;/em&gt;. Cambridge University Press, Cambridge, England, Second edition, 2016. &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>PLT</category></item><item><title>Const Correctness Issue of std::function</title><link>https://lesleylai.info/en/const-correcness-std-function</link><guid isPermaLink="true">https://lesleylai.info/en/const-correcness-std-function</guid><description>The const type qualifier is one of the jewels of the C++ language design. Surrounding by this feature, we devise the “const correctness” practice to prevent const objects from getting mutated. The const correctness rule is straight-forward to follow for implementation of the most classes, but it is ..</description><pubDate>Mon, 30 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;code&gt;const&lt;/code&gt; type qualifier is one of the jewels of the C++ language design. Surrounding by this feature, we devise the “&lt;code&gt;const&lt;/code&gt; correctness” practice to prevent &lt;code&gt;const&lt;/code&gt; objects from getting mutated. The &lt;code&gt;const&lt;/code&gt; correctness rule is straight-forward to follow for implementation of the most classes, but it is harder to heed for classes with type erasure. Unfortunately, the standard library type &lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/functional/function&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;std::function&lt;/code&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is implemented by type erasure; and due to short-sightedness, it becomes one of the ill-behaved citizens that doesn’t follow the const-correctness rule.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#the-problem&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The Problem&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;std::function&lt;/code&gt; has one const member &lt;code&gt;operator()&lt;/code&gt;, yet it can mutate the underlying function. For example,&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; f {[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]() &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;x; }};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;span&gt; // returns 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;span&gt; // returns 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The Document N4348&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; first formalized this concern. It states that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This violates not only basic tenets of &lt;code&gt;const-&lt;/code&gt;correctness, but also the data race avoidance guarantees in [res.on.data.races]/p3, which states that “A C++ standard library function shall not directly or indirectly modify objects accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-&lt;code&gt;const&lt;/code&gt; arguments, including &lt;code&gt;this&lt;/code&gt;”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;a href=&quot;#the-fix&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The Fix&lt;/h2&gt;
&lt;p&gt;Implementations of a &lt;code&gt;function&lt;/code&gt;-like class should have separate specializations for &lt;code&gt;const&lt;/code&gt; and non-&lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Sig&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; // not defined&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;... &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;(Args...)&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;... &lt;/span&gt;&lt;span&gt;Args&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;(Args...) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;operator()&lt;/code&gt; of the &lt;code&gt;const&lt;/code&gt; specialization should be annotated as &lt;code&gt;const&lt;/code&gt;, but the constructor of the &lt;code&gt;const&lt;/code&gt; specialization would not accept mutable function objects.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; f1 {[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]() { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x; }};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; // ok;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; f2 {[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]() &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;x; }};&lt;/span&gt;&lt;span&gt; // Does not compile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;On the other hand, &lt;code&gt;operator()&lt;/code&gt; of the non-&lt;code&gt;const&lt;/code&gt; specialization would not have &lt;code&gt;const&lt;/code&gt; type signature, so you cannot invoke the &lt;code&gt;const&lt;/code&gt; version of such functions at all:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; f1 {[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]() &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;x; }};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;span&gt; // ok&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; f2 {[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]() &lt;/span&gt;&lt;span&gt;mutable&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;x; }};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;f2&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;span&gt; // Does not compile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#the-future&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The Future&lt;/h2&gt;
&lt;p&gt;I don’t expect &lt;code&gt;std::function&lt;/code&gt; itself to have any change that breaks backward-compatibility. As of the time of this writing (December 2019), my bet is on the proposed &lt;code&gt;std::unique_function&lt;/code&gt; &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, which is a drop-in replacement of &lt;code&gt;std::function&lt;/code&gt; that fixes the const-correctness bug among other features. Once we have an alternative in standard, &lt;code&gt;std::function&lt;/code&gt; can be deprecated just like &lt;code&gt;std::auto_ptr&lt;/code&gt;. In the meantime, we can always implement &lt;code&gt;unique_function&lt;/code&gt; on our own, and I have a small library to implement that on &lt;a href=&quot;https://github.com/Beyond-Engine/functions&quot; target=&quot;_blank&quot;&gt;Github&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4348.html&quot; target=&quot;_blank&quot;&gt;Making std::function safe for concurrency&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0228r3.html&quot; target=&quot;_blank&quot;&gt;P0228R3 unique_function: a move-only std::function&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Coding</category><category>C++</category></item><item><title>Make Impossible State Unrepresentable, in C++</title><link>https://lesleylai.info/en/make-impossible-state-unrepresentable</link><guid isPermaLink="true">https://lesleylai.info/en/make-impossible-state-unrepresentable</guid><description>At CppCon 2019, I gave a lightning talk at called Make Impossible State Unrepresentable. Due to the nature of a 5 minutes lightning talk, it was handwavy, and I cut a lot of prepared contents to fit the time. This post is a deeper dive into the topic with more detailed explanations and examples.

Th..</description><pubDate>Sat, 26 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At &lt;a href=&quot;https://cppcon.org/&quot; target=&quot;_blank&quot;&gt;CppCon&lt;span&gt;&lt;/span&gt;&lt;/a&gt; 2019, I gave a lightning talk at called &lt;a href=&quot;https://youtu.be/hYyRrYwfy3k&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Make Impossible State Unrepresentable&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Due to the nature of a 5 minutes lightning talk, it was handwavy, and I cut a lot of prepared contents to fit the time. This post is a deeper dive into the topic with more detailed explanations and examples.&lt;/p&gt;
&lt;p&gt;The same practice in typed-functional programming communities inspires this topic. However, I do not consider this theme too “functional,” and it can certainly be applied to C++ or any other programming languages with a type system. The topic also has a strong relationship with “&lt;a href=&quot;https://en.wikipedia.org/wiki/Strong_and_weak_typing&quot; target=&quot;_blank&quot;&gt;strong typing&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.”&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#the-motivation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The motivation&lt;/h2&gt;
&lt;p&gt;Consider the following code snippet that I copied from a &lt;a href=&quot;https://vulkan-tutorial.com/&quot; target=&quot;_blank&quot;&gt;tutorial website&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for the &lt;a href=&quot;https://www.khronos.org/vulkan/&quot; target=&quot;_blank&quot;&gt;Vulkan Graphics API&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Apparently, many people directly copy this tutorial to their codebase.&lt;/p&gt;
&lt;p&gt;In the snippet, we have a struct of indices for different queues, and we first query the indices and use them to refer to those queues later.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;QueueFamilyIndices&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::optional&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; graphics;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::optional&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; present;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isComplete&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;graphics&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;has_value&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;present&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;has_value&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;QueueFamilyIndices&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;findQueueFamilies&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;/*...*/&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;QueueFamilyIndices indices;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; queue: queues) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;/* queue i support graphics */&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;indices&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;graphics&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;/* queue i support present */&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;indices&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;present&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;indices&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;isComplete&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; indices;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In this particular case, the function &lt;code&gt;findQueueFamilies&lt;/code&gt; is the only place where we can have uninitialized queue indices, so why no get rid of all the &lt;code&gt;optional&lt;/code&gt;s in the struct:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;QueueFamilyIndices&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; graphics;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; present;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;QueueFamilyIndices&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;findQueueFamilies&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;/*...*/&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::optional&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; graphicsFamily &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::nullopt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::optional&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; presentFamily &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::nullopt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; queue: queues) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;/* queue i support graphics */&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;graphicsFamily &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;/* queue i support present */&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;presentFamily &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (graphicsFamily &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; presentFamily) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; QueueFamilyIndices{&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;graphicsFamily, &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;presentFamily};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::nullopt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The memory footprint of &lt;code&gt;QueueFamilyIndices&lt;/code&gt; gets reduced from 16 bytes to 8 bytes. The reason is partly that we no longer store unnecessary information, and partly because of the inefficient alignments of multiple &lt;code&gt;std::optional&lt;/code&gt; from the first &lt;code&gt;struct&lt;/code&gt;.&lt;/p&gt;
&lt;aside&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; j;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; has_i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; has_j;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; i;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; j;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the above snippet, the &lt;code&gt;sizeof(A)&lt;/code&gt; is 16 bytes while the &lt;code&gt;sizeof(B)&lt;/code&gt; is only 12 bytes.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;We also reduced the need for assertions or runtime checking. Notice the &lt;code&gt;isComplete&lt;/code&gt; function goes away for the second case, as we don’t need to call this logic multiple times. In the first case, we would no be that confident, since we can have a bug that left &lt;code&gt;QueueFamilyIndices&lt;/code&gt; uninitialized.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#algebraic-data-types&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Algebraic Data Types&lt;/h2&gt;
&lt;p&gt;The above example demonstrates the usage of algebraic sum types (&lt;code&gt;optional&lt;/code&gt; or &lt;code&gt;variant&lt;/code&gt;), albeit in an inefficient way at first. Those types belong to the new addition of the “vocabulary types” in C++17, though they have a long history in other programming languages and third-party C++ libraries. The name “sum type” comes from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cardinality&quot; target=&quot;_blank&quot;&gt;cardinality&lt;span&gt;&lt;/span&gt;&lt;/a&gt; of the set of the possible state of those types. Similarly, the more familiar &lt;code&gt;struct&lt;/code&gt; or tuple are called “product type” because their cardinality is the product of the cardinality of all of their fields. Sum types are sometimes also called “tagged union” or “variant type”.&lt;/p&gt;
&lt;p&gt;Algebraic sum type has an advantage on &lt;a href=&quot;https://www.bfilipek.com/2019/06/fsm-variant-game.html&quot; target=&quot;_blank&quot;&gt;building state machines&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. A textbook example of such use case is network connection:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Connection&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Closed&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Connecting&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IP ip;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Connected&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IP ip;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Id id;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::variant&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Closed, Connecting, Connected&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; state;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This implementation faithfully represents the data used by each state. For example, it doesn’t make sense to store an IP address for &lt;code&gt;Connection&lt;/code&gt; is it is &lt;code&gt;Closed&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#inheritance-hierarchy-vs-sum-type&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Inheritance Hierarchy vs. Sum Type&lt;/h3&gt;
&lt;p&gt;Both sum types and inheritance are used for &lt;em&gt;runtime polymorphism&lt;/em&gt;. In other words, only use them when you need runtime polymorphism. Sum types add one major constraint over inheritance. Inheritance is &lt;a href=&quot;https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle&quot; target=&quot;_blank&quot;&gt;open to extension&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, while sum types are closed. The constraint is not necessarily a bad thing. For example, because as the compiler knows maximum size information statically, it can put the whole &lt;code&gt;variant&lt;/code&gt; object on the stack.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;When I talk about “inheritance hierarchy” here, the only focus is the virtual-dispatch enabled inheritance. Notably, I do not include &lt;a href=&quot;https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern&quot; target=&quot;_blank&quot;&gt;CRTP&lt;span&gt;&lt;/span&gt;&lt;/a&gt; or other usages of inheritances without any virtual functions that aim to reuse code instead of enabling subtyping polymorphism.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In theory, dispatch over &lt;code&gt;variant&lt;/code&gt; can be faster than the virtual dispatch, though none of the current implementations of &lt;code&gt;std::visit&lt;/code&gt; are faster than virtual. However, in a potential future C++ version with language variant and pattern matching, there is evidence &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; that variant would provide an advantage.&lt;/p&gt;
&lt;p&gt;However, the “open to extension” property of inheritance does prove useful from time to time. For example, consider that you are working on a compiler, you may represent your expression in a traditional OO-way like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; { ... };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ConstExpr&lt;/span&gt;&lt;span&gt; : Expr { ... };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LambdaExpr&lt;/span&gt;&lt;span&gt; : Expr { ... };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ApplyExpr&lt;/span&gt;&lt;span&gt; : Expr { ... };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Adding compilation errors is as simple as adding derived classes like &lt;code&gt;SyntaxErrorExpr&lt;/code&gt; and &lt;code&gt;TypeErrorExpr&lt;/code&gt; into the corresponding stages, and those errors are completely hidden between stages. By contrast, with sum type, one option is to create a mess like:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Expr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::variant&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ConstExpr, LambdaExpr, ApplyExpr,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;SyntaxErrorExpr, TypeErrorExpr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This approach forces us to handle &lt;code&gt;TypeErrorExpr&lt;/code&gt; in the &lt;em&gt;parser&lt;/em&gt;. Another option is to pay extra overhead and to wrap every &lt;code&gt;Expr&lt;/code&gt; into an &lt;a href=&quot;http://www7.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0323r7.html&quot; target=&quot;_blank&quot;&gt;expected&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Both alternatives are less than ideal, and the problem becomes even bigger if the abstract syntax tree becomes more complex and contains a hierarchy.&lt;/p&gt;
&lt;p&gt;Another type of polymorphism is &lt;a href=&quot;https://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Row_polymorphism&quot; target=&quot;_blank&quot;&gt;row polymorphism&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Row polymorphism only considers features and structures of a type. Like inheritance, row polymorphism is also open to extension, so it shares many advantages as inheritance. Row polymorphism is arguably a better alternative to virtual inheritance &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;. Though row polymorphism is exactly what C++ &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot; target=&quot;_blank&quot;&gt;concept&lt;span&gt;&lt;/span&gt;&lt;/a&gt; achieves, C++ lacks support build-in support of it for runtime polymorphism. &lt;a href=&quot;https://gobyexample.com/interfaces&quot; target=&quot;_blank&quot;&gt;Go&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/interfaces.html&quot; target=&quot;_blank&quot;&gt;Typescript&lt;span&gt;&lt;/span&gt;&lt;/a&gt; interfaces and &lt;a href=&quot;https://doc.rust-lang.org/rust-by-example/trait.html&quot; target=&quot;_blank&quot;&gt;Rust trait&lt;span&gt;&lt;/span&gt;&lt;/a&gt; are examples of such language features. In C++, runtime row polymorphism can be implemented by doing &lt;a href=&quot;https://quuxplusone.github.io/blog/2019/03/18/what-is-type-erasure/&quot; target=&quot;_blank&quot;&gt;type-erasure&lt;span&gt;&lt;/span&gt;&lt;/a&gt; manually.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#data-modeling&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Data Modeling&lt;/h2&gt;
&lt;p&gt;All of the above discussions lead to &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_modeling&quot; target=&quot;_blank&quot;&gt;data modeling&lt;span&gt;&lt;/span&gt;&lt;/a&gt; — defining and analyzing data requirements and define data models accordingly. Both &lt;a href=&quot;https://en.wikipedia.org/wiki/Data-oriented_design&quot; target=&quot;_blank&quot;&gt;data-oriented design&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and functional programming people like to talk about Data modeling.&lt;/p&gt;
&lt;p&gt;From the point of view of an object-oriented developer, data modeling is similar to class design. Classes often work as self-contained entities that know how to do operations on themselves. However, such an approach requires packing all “logical related” data into one structure, and it often does not make sense. For example, below is how &lt;a href=&quot;https://github.com/mmp/pbrt-v3&quot; target=&quot;_blank&quot;&gt;pbrt-v3&lt;span&gt;&lt;/span&gt;&lt;/a&gt; implements triangles:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TriangleMesh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; vertexIndices;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::unique_ptr&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Point3f[]&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; p;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// other data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Triangle&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Triangle operations&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::shared_ptr&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;TriangleMesh&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; mesh;&lt;/span&gt;&lt;span&gt; // back pointer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;v;&lt;/span&gt;&lt;span&gt; // A pointer to vertex indices&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Each &lt;code&gt;Triangle&lt;/code&gt; need to store a back pointer to operate on itself. Moreover, there is no guarantee that the pointer &lt;code&gt;v&lt;/code&gt; is not dangled. In this particular example, programmers make sure that &lt;code&gt;v&lt;/code&gt; always points to memory managed by &lt;code&gt;TriangleMesh&lt;/code&gt;.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Aside from valid use cases on shared ownership, &lt;code&gt;std::shared_ptr&lt;/code&gt; is often misused to represent “vague ownership.”&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;If we abandon the idea that triangles must know how to operates on themselves, then the triangles become just indices to the vertices:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Triangle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; first;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; second;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; third;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TriangleMesh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Triangle operations&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Triangle&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; triangles;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::unique_ptr&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Point3f[]&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; p;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// other data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Since we no longer need to worry about the dangling of indices, we don’t need reference counting anymore.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#transform-the-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Transform the API&lt;/h2&gt;
&lt;p&gt;Sometimes following the guideline of better data modeling means changing the APIs. Such a change would make the API easier to use and harder to misuse, so it is better to start early than later.&lt;/p&gt;
&lt;p&gt;Below is another example from graphics programming where we have commands to submit to GPU. We don’t directly push the data to GPU, but instead, cache them in a &lt;code&gt;CommandBuffer&lt;/code&gt; object that we can batch submit later.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_draw_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vertex_offset&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                   &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;instance_count&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_draw_indirect_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;void*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;indirect&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_bind_graphics_pipeline_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;GraphicsPipelineHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pipeline&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This graphics API directly maps to lower-level APIs like Vulkan and DirectX12 nicely and is very flexible. There is one huge drawback, nevertheless. The graphics pipeline object encapsulates all the logic of drawing, like how to interpret data we sent to the GPU. However, in the current API, you can freely start to draw objects without bind to a graphics pipeline:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;CommandBuffer buffer;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;push_draw_command&lt;/span&gt;&lt;span&gt;(count, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;queue&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;submit&lt;/span&gt;&lt;span&gt;(buffer);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;One naive forward modification is putting the reference of the graphics pipeline inside each command. Nonetheless, we are paying an extra overhead here as the need to check if the graphics pipeline stays the same. If it is, we don’t need to rebind the pipeline again, since rebinding a graphics pipeline can be a costly operation in GPU. Another optimization for this model is to add sorting against the graphics pipeline on top of each command. Such optimization, however, also introduces additional overhead.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_draw_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;GraphicsPipelineHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pipeline&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                   &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vertex_offset&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;instance_count&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_draw_indirect_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;GraphicsPipelineHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pipeline&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                            &lt;/span&gt;&lt;span&gt;void*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;indirect&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A better fix is to introduce another structure, &lt;code&gt;DrawingCommandbuffer&lt;/code&gt;, that contains a graphics pipeline and draw commands. In this model, there is no need for checking or sorting, and we can quickly build &lt;code&gt;DrawingCommandbuffer&lt;/code&gt; in parallel.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DrawingCommandbuffer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;DrawingCommandbuffer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;GraphicsPipelineHandle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pipeline&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;DrawingCommandbuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_draw_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vertex_offset&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                   &lt;/span&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;instance_count&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;DrawingCommandbuffer&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_draw_indirect_command&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;void*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;indirect&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CommandBuffer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push_drawing_commands&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;DrawingCommandBuffer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Note that we can implement &lt;code&gt;DrawingCommandbuffer&lt;/code&gt; in terms of Secondary Command Buffers of Vulkan, but there are no restrictions on how it must be implemented. Thus, implementations of different lower-level graphics APIs can use completely different approaches.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#limitations&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Limitations&lt;/h2&gt;
&lt;p&gt;Not all invariant can be checked at compile-time, and that is why many programming languages support &lt;a href=&quot;https://en.wikipedia.org/wiki/Design_by_contract&quot; target=&quot;_blank&quot;&gt;contract&lt;span&gt;&lt;/span&gt;&lt;/a&gt; or at least runtime assertion. However, even counting all the “compile-time known state,” there are limitations of applying “make impossible state unrepresentable” in C++. Some of them are due to the design of the C++ type system, and others are due to the performance requirements for C++ applications faces.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#the-curious-case-of-move-semantics&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The curious case of Move semantics&lt;/h3&gt;
&lt;p&gt;I love C++11 move semantics. However, despite move semantics solving a lot of problems, it opens a hole in the C++ type system. Consider a class that wraps resource with underlying C-style API. In the C++98 area, we achieved the perfect RAII since the resource’ lifetime is tied with the lifetime of the object.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Would never be nullptr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;GLFWwindow&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; window;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We introduced move semantics to make it movable. However, to enable move semantics for our resource handle, we created a pointer-like object. The reason is that the after move states must be valid; to have a valid after-move state, we are forced to represent the empty state in our class. That is why we have &lt;code&gt;unique_ptr&lt;/code&gt; but no &lt;code&gt;unique_reference&lt;/code&gt; in the C++ standard library. And it is also partly why people repeatedly propose &lt;em&gt;&lt;a href=&quot;http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4034.pdf&quot; target=&quot;_blank&quot;&gt;destructive move&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Another reason for &lt;em&gt;destructive move&lt;/em&gt; is performance. The performance improvements of move can be accomplished by &lt;a href=&quot;https://quuxplusone.github.io/blog/&quot; target=&quot;_blank&quot;&gt;Arthur O’Dwyer&lt;span&gt;&lt;/span&gt;&lt;/a&gt; ‘s great but less ambitious &lt;em&gt;trivially relocatable&lt;/em&gt; [&lt;a href=&quot;https://rawgit.com/Quuxplusone/draft/gh-pages/d1144-object-relocation.html&quot; target=&quot;_blank&quot;&gt;P1144&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] proposal.&lt;/p&gt;
&lt;/aside&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Window&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; : &lt;/span&gt;&lt;span&gt;window&lt;/span&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;window&lt;/span&gt;&lt;span&gt;} {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;window&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nullptr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;GLFWwindow&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; window;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Utilizing the static type system well, we can eradicate the possibility of runtime invariant violations in a group of cases. This approach decreases the possibility of insane debugging sessions and the need for aggressive assertions. It also helps testing because we don’t have to test what a static type system guaranteed. Moreover, we can see a performance gain sometimes by thinking about how to model data more carefully.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/solodon4/Mach7&quot; target=&quot;_blank&quot;&gt;Mach7: Pattern Matching for C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=QGcVXgEVMJg&amp;amp;feature=youtu.be&quot; target=&quot;_blank&quot;&gt;Better Code: Runtime Polymorphism - Sean Parent&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=VSlBhAOLtFA&quot; target=&quot;_blank&quot;&gt;Simon Brand: “How Rust gets polymorphism right”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gVGtNFg4ay0&quot; target=&quot;_blank&quot;&gt;CppCon 2017: Louis Dionne “Runtime Polymorphism: Back to the Basics”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mropert.github.io/2017/11/30/polymorphic_ducks/&quot; target=&quot;_blank&quot;&gt;Mathieu Ropert: Polymorphic ducks&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ckY7Pc-A9Xc&quot; target=&quot;_blank&quot;&gt;CppCon 2018: Borislav Stanimirov “DynaMix: A New Take on Polymorphism”&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Coding</category><category>C++</category><category>DOD</category><category>FP</category></item><item><title>We are defining assignment operators wrong.</title><link>https://lesleylai.info/en/type-of-assignment-operators</link><guid isPermaLink="true">https://lesleylai.info/en/type-of-assignment-operators</guid><description>Update: Apparently there is a WG21 paper on this subject that goes in much more detailed than my post. I am surprised that I missed his CppCon talk on this topic and come into the silimar conclusion.

One principle of C++ operator overloading is that the behavior of overloaded operators should be si..</description><pubDate>Mon, 14 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Update: Apparently there is a WG21 &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1906r0.pdf&quot; target=&quot;_blank&quot;&gt;paper&lt;span&gt;&lt;/span&gt;&lt;/a&gt; on this subject that goes in much more detailed than my post. I am surprised that I missed his CppCon talk on this topic and come into the silimar conclusion.&lt;/p&gt;
&lt;p&gt;One principle of C++ operator overloading is that the behavior of overloaded operators should be similar to the counterparts on fundamental types. For the most part, we are doing a decent job. However, the way we define assignment operators leaves some surprise.&lt;/p&gt;
&lt;p&gt;Consider the following code snippet:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; // error: lvalue required as left operand of assignment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It is complete nonsense in most of the programming languages. And indeed, no compilers are happy about it,&lt;/p&gt;
&lt;p&gt;However, for a class type, it is perfectly fine to assign to a temporary:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;S{} &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; S{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The reason is that the type signature of the assignment operators, whether if they are compiler-generated or if we define manually, does not exclude r-value types:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Perfectly happy with `*this` being both lvalue or rvalue&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And an easy fix is only to define the lvalue reference overload of assignment:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; S&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;S&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; S&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;S{} &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; S{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In this case, all three major compilers created a somewhat mystical error message, just like what usually happens when overload resolution fails, but at least it will not compile.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#does-this-issue-even-matters&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Does this issue even matters?&lt;/h2&gt;
&lt;p&gt;To me, this concern is more of a theoretical nuisance than a serious problem. I can’t picture any seasoned programmers who inadvertently assigning to an rvalue. It has the potential to be a problem to absolute beginners if they haven’t touch any programming languages before. It can also confuse beginners when they write a single equal when they want double equals. If they follow the best practice of declaring as much as &lt;code&gt;const&lt;/code&gt; as possible, then the left-hand side of an assignment will be either a const value or a temporary. And such error can be caught by making the assignments l-value reference qualified.&lt;/p&gt;
&lt;p&gt;It is still a good idea to follow rule-of-zero and do not touch any assignment operators. However, when you do need to define assignments, consider making only the lvalue reference overload. If C++ does get something like the &lt;a href=&quot;https://vittorioromeo.info/index/blog/fixing_cpp_with_epochs.html&quot; target=&quot;_blank&quot;&gt;epoch&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, then we can potentially add reference qualifiers to assignment operators of standard library types, for example, &lt;code&gt;std::string&lt;/code&gt;.&lt;/p&gt;</content:encoded><category>Coding</category><category>C++</category></item><item><title>CppCon 2019 Trip Report</title><link>https://lesleylai.info/en/cppcon2019</link><guid isPermaLink="true">https://lesleylai.info/en/cppcon2019</guid><description>What a week we had! CppCon 2019 is by far the best CppCon that I’ve ever attended. There are contents that interest me on every time slot, and for a lot of time there are conflict so that it is hard to decide which talk to go to.


PRE AND POST-CONFERENCE CLASSES

 * Arthur O’Dwyer’s Standard Librar..</description><pubDate>Sun, 22 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What a week we had! CppCon 2019 is by far the best CppCon that I’ve ever attended. There are contents that interest me on every time slot, and for a lot of time there are conflict so that it is hard to decide which talk to go to.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#pre-and-post-conference-classes&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Pre and post-conference classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://quuxplusone.github.io/blog/&quot; target=&quot;_blank&quot;&gt;Arthur O’Dwyer&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;&lt;a href=&quot;https://quuxplusone.github.io/from-scratch/&quot; target=&quot;_blank&quot;&gt;Standard Library From Scratch&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/em&gt; teaches us the implementations of type-erased containers (&lt;code&gt;any&lt;/code&gt; and &lt;code&gt;function&lt;/code&gt;), synchronization primitives, smart pointers, and a bunch of meta-programming utilities. This course makes me more confident about type erasure, small-object optimization, and meta-programming.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gordon Brown and Micheal Wong’s &lt;em&gt;&lt;a href=&quot;https://github.com/Aerialmantis/cppcon-parallelism-class&quot; target=&quot;_blank&quot;&gt;Parallelism in Modern C++: From CPU to GPU&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/em&gt; talks about general parallel programming principles and &lt;a href=&quot;https://www.khronos.org/sycl/&quot; target=&quot;_blank&quot;&gt;SYCL&lt;span&gt;&lt;/span&gt;&lt;/a&gt; programming. I didn’t have much experience in GPGPU and never touched SYCL before, but I find that many concepts maps nicely to the &lt;a href=&quot;https://www.khronos.org/vulkan/&quot; target=&quot;_blank&quot;&gt;Vulkan&lt;span&gt;&lt;/span&gt;&lt;/a&gt; Graphics API.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#the-keynotes&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The keynotes&lt;/h2&gt;
&lt;p&gt;CppCon this year have one keynote for each day, and all the keynotes are high quality.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://www.stroustrup.com/&quot; target=&quot;_blank&quot;&gt;Bjarne Stroustrup&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;C++20: C++ at 40&lt;/em&gt; [&lt;a href=&quot;https://www.youtube.com/watch?v=u_ij0YNkFUs&quot; target=&quot;_blank&quot;&gt;video&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] talks about the current status of C++ from the perspective of its creator. Nothing substantially surprising is in this talk, but the combination of C++ features like modules and concept has already completely transformed this language into a new height. Bjarne also talked about his vision of future C++.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://erdani.com/&quot; target=&quot;_blank&quot;&gt;Andrei Alexandrescu&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;Speed Is Found In The Minds of People&lt;/em&gt; [&lt;a href=&quot;https://www.youtube.com/watch?v=FJJTYQYB1JQ&amp;amp;t=4552s&quot; target=&quot;_blank&quot;&gt;video&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] is both entertaining and inspiring. It makes me rethink about algorithms and optimization.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ben Smith - &lt;em&gt;Applied WebAssembly: Compiling and Running C++ in Your Web Browser&lt;/em&gt; [&lt;a href=&quot;https://www.youtube.com/watch?v=5N4b-rU-OAA&quot; target=&quot;_blank&quot;&gt;video&lt;span&gt;&lt;/span&gt;&lt;/a&gt;]. Interning in a &lt;a href=&quot;https://www.sketchup.com/&quot; target=&quot;_blank&quot;&gt;company&lt;span&gt;&lt;/span&gt;&lt;/a&gt; where we have a web assembly &lt;a href=&quot;https://app.sketchup.com/app&quot; target=&quot;_blank&quot;&gt;product&lt;span&gt;&lt;/span&gt;&lt;/a&gt; using the C++ codebase, I am delighted that people are spreading this practice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://sean-parent.stlab.cc/&quot; target=&quot;_blank&quot;&gt;Sean Parent&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;Better Code: Relationships&lt;/em&gt; [&lt;a href=&quot;https://www.youtube.com/watch?v=ejF6qqohp3M&quot; target=&quot;_blank&quot;&gt;video&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] continues his “Better Code” series. This time he was talking about theories of relationships between objects and how they guide us to architect software.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://herbsutter.com/&quot; target=&quot;_blank&quot;&gt;Herb Sutter&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;De-fragmenting C++: Making Exceptions and RTTI More Affordable and Usable&lt;/em&gt; [&lt;a href=&quot;https://www.youtube.com/watch?v=ARYP83yNAWk&quot; target=&quot;_blank&quot;&gt;video&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] naturally grab everyone’s attention. A large part of the communities is not satisfied, which the current status of exceptions and RTTI, so Herb’s series of proposals will help tremendously. Herb gives the same talk in my user group in March.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#personal-high-light&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Personal high light&lt;/h2&gt;
&lt;p&gt;There are so many great talks in this year’s CppCon, so I can only mention some of them that I attended and impressed me the most.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bsky.app/profile/blelbach.bsky.social&quot; target=&quot;_blank&quot;&gt;Bryce Lelbach&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;The C++20 Synchronization Library&lt;/em&gt; [&lt;a href=&quot;https://youtu.be/Zcqwb3CWqs4&quot; target=&quot;_blank&quot;&gt;video&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] is probably the best concurrency talk I heard in CppCon this year. It went through not only C++20 synchronization primitives but how to use them to build a task system. I plan to watch it several times until absorbing all its content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alisdair Meredith and Pablo Halpern’s &lt;em&gt;Getting Allocators out of our way&lt;/em&gt; [&lt;a href=&quot;https://github.com/CppCon/CppCon2019/blob/master/Presentations/getting_allocators_out_of_our_way/getting_allocators_out_of_our_way__alisdair_meredith__pablo_halpern__cppcon_2019.pdf&quot; target=&quot;_blank&quot;&gt;slides&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] proposed an interesting language extension to simplify the writing of allocator-aware classes on top of the current &lt;code&gt;pmr&lt;/code&gt; model. The basic idea is that allocators are no longer a regular parameter, but a special parameter that we can optionally provide with a different syntax. The extension works like Scala’s &lt;a href=&quot;https://docs.scala-lang.org/tour/implicit-parameters.html&quot; target=&quot;_blank&quot;&gt;implicit parameter&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, and it can have potential use to other structures like executors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bsky.app/profile/lefticus.bsky.social&quot; target=&quot;_blank&quot;&gt;Jason Turner&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;C++ Code Smell&lt;/em&gt; [&lt;a href=&quot;https://github.com/CppCon/CppCon2019/blob/master/Presentations/cpp_code_smells/cpp_code_smells__jason_turner__cppcon_2019.pdf&quot; target=&quot;_blank&quot;&gt;slides&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] finally convinced me that &lt;code&gt;const&lt;/code&gt; function parameters have an advantage with a very simple example, which I was doubtful when he talked about it last year.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mropert.github.io/&quot; target=&quot;_blank&quot;&gt;Mathieu Ropert&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s &lt;em&gt;This Videogame Programmer Used the STL and You Will Never Guess What Happened Next&lt;/em&gt; [&lt;a href=&quot;https://github.com/CppCon/CppCon2019/blob/master/Presentations/this_videogame_programmer_used_the_stl/this_videogame_programmer_used_the_stl__mathieu_ropert__cppcon_2019.pdf&quot; target=&quot;_blank&quot;&gt;slides&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] demystifies some common myth against C++ standard library, including the common concern of “debugging performance.” It also explains when should you (not) use STL.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;
&lt;p&gt;Seriously, this name is tooooo long.&lt;/p&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://xania.org/&quot; target=&quot;_blank&quot;&gt;Matt Godbolt&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s “Path Tracing Three Ways” [&lt;a href=&quot;https://mattgodbolt.github.io/pt-three-ways-pres/#/&quot; target=&quot;_blank&quot;&gt;slides&lt;span&gt;&lt;/span&gt;&lt;/a&gt;] implements a same primitive path tracer in three C++ styles— object-oriented, functional, and data-oriented design. He analyze the performance and compares their strengths and weaknesses. One interesting detour is that a naively designed data-oriented code without dynamic polymorphism can be even slower than its OO counterpart because of branch misprediction (which DOD tries to avoid). The fix he applied not only improved the data-oriented version but also significantly increase the speed of the functional version. One thing I wonder is that in the particular case of path tracing, how much performance advantage of data-oriented design can be preserved when adding acceleration data-structures.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href=&quot;#my-lighting-talk&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;My lighting talk&lt;/h2&gt;
&lt;p&gt;I gave a lightning talk on Wednesday night called &lt;em&gt;Make impossible state unrepresentable&lt;/em&gt; inspired by the typed functional languages communities. In the lighting talk, I mentioned how to design data and types in C++ to leverage the static type system so that invariants breaking becomes impossible in some instances.&lt;/p&gt;
&lt;p&gt;This talk is my first presentation to give in front of the public instead of a university or meetup setting. I was nervous, but I managed to finish it. I also found that it is extremely hard to fit content into five minutes, as I cut more than half of the original slides I prepared. Thank CppCon for giving me this opportunity, and thanks &lt;a href=&quot;https://levelofindirection.com/index.html&quot; target=&quot;_blank&quot;&gt;Phil Nash&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for organizing the lighting talks well!&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As a student, attending a conference at school time always gives me immense pressure in term of school works. However, CppCon was and is always worthwhile. It is a pleasure to be surrounded by so many extraordinary people in the C++ communities, and “C++ heroes” that I usually can only see online. Thank everyone I met for being awesome for the whole week. I can’t wait to attend the CppCon and meet you all next year!&lt;/p&gt;</content:encoded><category>C++</category><category>Event</category></item><item><title>ACM Siggraph 2019 Trip Report</title><link>https://lesleylai.info/en/siggraph2019</link><guid isPermaLink="true">https://lesleylai.info/en/siggraph2019</guid><description>This year, several of the coworkers and I at Trimble SketchUp attended ACM Special Interest Group in Graphics (Siggraph) conference. It is my first time attending such a big gathering. The week is exciting, exhaustion, and also extremely rewarding for me.



This year the conference location is Los ..</description><pubDate>Wed, 07 Aug 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This year, several of the coworkers and I at &lt;a href=&quot;https://www.sketchup.com/&quot; target=&quot;_blank&quot;&gt;Trimble SketchUp&lt;span&gt;&lt;/span&gt;&lt;/a&gt; attended ACM &lt;a href=&quot;https://s2019.siggraph.org/&quot; target=&quot;_blank&quot;&gt;Special Interest Group in Graphics (Siggraph) conference&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. It is my first time attending such a big gathering. The week is exciting, exhaustion, and also extremely rewarding for me.&lt;/p&gt;
&lt;div&gt;&lt;img src=&quot;/_astro/pier-sunset.Bv-1bLty_6dBAP.webp&quot; alt=&quot;Sunset at the Santa Monica pier&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/div&gt;
&lt;p&gt;This year the conference location is Los Angeles, so we had the chance to have a tour to the pier, taste different seafood, and watch the sunset. We also had nerdy jokes about the pier floor is just a displacement map, and the sunset can be rendered by some &lt;a href=&quot;https://www.shadertoy.com/view/Ml2cWG&quot; target=&quot;_blank&quot;&gt;shader hack&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#ray-tracing-on-sunday&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Ray Tracing on Sunday&lt;/h2&gt;
&lt;p&gt;The spotlight of this year’s Siggraph is still ray tracing after Nvidia announce their &lt;a href=&quot;https://www.nvidia.com/en-us/geforce/20-series/&quot; target=&quot;_blank&quot;&gt;Geforce RTX&lt;span&gt;&lt;/span&gt;&lt;/a&gt; GPUs with ray-tracing capacity a year ago.&lt;/p&gt;
&lt;p&gt;As a &lt;a href=&quot;https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&quot; target=&quot;_blank&quot;&gt;ray-tracing&lt;span&gt;&lt;/span&gt;&lt;/a&gt; fanatic, I am glad to see the technology I like becomes more and more popular. It is said that “ray tracing is not slow; it is the computers.” Fortunately, we are just entering this revolution that, for the first time, computers are fast enough to do serious ray tracing works in real-time. I spent the whole Sunday on Ray-tracing related sessions. The session on the morning is &lt;a href=&quot;https://sites.google.com/view/arewedonewithraytracing&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Are We Done With Ray Tracing?&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; Spoiler alert, as you may expect, the answer is no. The area is still a warm bed of new researches. Further, with the advent of real-time ray-tracing, new challenges arose like denoising on images generated by very-low sample size, effectively updating of acceleration structures.&lt;/p&gt;
&lt;p&gt;Different speakers had different vision of how fast the ray-tracing adoption will be. &lt;a href=&quot;https://casual-effects.com/morgan/index.html&quot; target=&quot;_blank&quot;&gt;Morgan McGuire&lt;span&gt;&lt;/span&gt;&lt;/a&gt; of Nvidia thinks that ray-tracing pipeline will become mainstream in real-time graphics in 5 years. By contrast, &lt;a href=&quot;https://colinbarrebrisebois.com&quot; target=&quot;_blank&quot;&gt;Colin Barré-Brisebois&lt;span&gt;&lt;/span&gt;&lt;/a&gt; for EA is much more conservative, considering rasterization/ray-tracing hybrid rendering-pipeline will be the future for a long time. I am more aligned with the latter opinion because ray-tracing are still much more expensive, and the hybrid approaches are already producing amazing results. To be honest, as long as we do not adopt a full-blown path-tracing approach (which still have prohibitive cost for current large real-time applications), I don’t think produced graphics quality of single real-tracing pipeline or rasterization will have a big difference. However, ray-tracing may decrease maintainance gain, especially for small teams and projects, since a completely ray-tracing pipeline will drastically decrease the complexity of current beastly graphics pipeline. By contrast, AAA shops’ graphics pipeline will be more complicated because they need to support both hybrid ray-tracing and fallbacks. I attended &lt;em&gt;Introduction to Real-Time Ray Tracing&lt;/em&gt; afternoon, which was on the same topic but covered more basic and detailed material, from &lt;a href=&quot;https://research.nvidia.com/person/peter-shirley&quot; target=&quot;_blank&quot;&gt;Peter Shirley&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s ray tracing introduction to how to write a simple DirectX ray-tracing program.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#monday-advances-in-real-time-rendering-and-animated-shorts&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Monday: Advances in Real-Time Rendering, and Animated Shorts&lt;/h2&gt;
&lt;p&gt;My colleges and I spent most of the Monday attending “&lt;a href=&quot;http://advances.realtimerendering.com/s2019/index.htm&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Advances in Real-Time Rendering in Games&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;” part 1 and 2. It is astonishing how many crazy new methods in real-time rendering get developed, from strand-based hair rendering to ocean wave simulation. There are just too many goodies for me to justify them all.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://s2019.siggraph.org/conference/programs-events/computer-animation-festival/electronic-theater/&quot; target=&quot;_blank&quot;&gt;Electronic Theater&lt;span&gt;&lt;/span&gt;&lt;/a&gt; at night was a fun event. We saw a lot of great works of animation artists this year. However, All of us felt that this year’s demos have overly depressing and emotional themes in general. There were excessively too many aminations focuses on the loneliness in an industrial society or the evil side of human nature.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#tuesday-vulkan-ray-tracing-roundtable&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Tuesday: Vulkan, Ray Tracing Roundtable&lt;/h2&gt;
&lt;p&gt;On Tuesday we went to &lt;a href=&quot;https://www.lunarg.com/wp-content/uploads/2019/07/LunarG-Validation-Layer-BoF.pdf&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Best Practices for Using and Contributing to the Vulkan Validation Layers&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.lunarg.com/wp-content/uploads/2019/07/LunarG-SDK-BoF.pdf&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Vulkan SDK Update and Community Feedback&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; from &lt;a href=&quot;https://www.lunarg.com/&quot; target=&quot;_blank&quot;&gt;LunarG&lt;span&gt;&lt;/span&gt;&lt;/a&gt; on Vulkan SDK. I am still very new to Vulkan, but I am impressed about how much work LunarG folks put into the SDK to make using Vulkan a better experience.&lt;/p&gt;
&lt;p&gt;I also went to the &lt;em&gt;Ray Tracing Roundtable&lt;/em&gt; organized by &lt;a href=&quot;https://erich.realtimerendering.com/&quot; target=&quot;_blank&quot;&gt;Eric Haines&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. People interested in ray tracing gathered in small groups and talked about news and advancement of ray tracing. It was an astounding experience that people like me could chat with heroes in the field face to face.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#wednesday-and-thursday&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Wednesday and Thursday&lt;/h2&gt;
&lt;p&gt;I have an ambition of making the &lt;a href=&quot;https://cu-computer-graphics-group.netlify.com/&quot; target=&quot;_blank&quot;&gt;CU Computer Graphics Group&lt;span&gt;&lt;/span&gt;&lt;/a&gt; a Siggraph chapter, so I went to &lt;em&gt;ACM SIGGRAPH Chapters Fast Forward and Startup Meeting&lt;/em&gt; Wednesday morning. I then went to &lt;a href=&quot;https://s2019.siggraph.org/presentation/?id=gensub_171&amp;amp;sess=sess193&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;An Introduction to Physics-Based Animation&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; afternoon, which compressed semester-worth materials into three and a half hours. On Thursday morning I went to &lt;em&gt;Differentiable Graphics With Tensorflow 2.0&lt;/em&gt;. The idea of Differentiable Rendering sounds exciting, and it is always good to see applications of machine learning in graphics beyond denoising. Nevertheless, I felt that it is hard for me to come up with a useful use case for it. Maybe I need to delve into this technique more in the future.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#exhibition&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Exhibition&lt;/h2&gt;
&lt;div&gt;&lt;img src=&quot;/_astro/exhibition.DIfj4ftd_25tx13.webp&quot; alt=&quot;Siggraph 2019 Exhibition&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/div&gt;
&lt;p&gt;Various companies have exhibitions and live demos in Siggraph. As with everything else, a lot of excitement around the exhibition is related to real-time ray-tracing. There were a lot of companies that demonstrated their motion capture techniques and streamed the results into a game engine. One of the particularly striking shops implemented a VR avatar that will always have eye contact with you after you move.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#conclusion-an-inspiring-year-to-learn-graphics&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion: An inspiring year to learn Graphics&lt;/h2&gt;
&lt;p&gt;The conference itself is just five days, but it leaves me with year-worth materials to learn. I took notes on several new technologists and libraries to play and more than ten papers that I want to read. Also, due to time conflict, I can’t attend all the sessions that I am interested in. There are still several intriguing talks and workshops I want to watch afterward, including &lt;em&gt;A Fast Forward through Ray Tracing Gems&lt;/em&gt;, &lt;em&gt;Optimizing and Deploying Ray-Traced Dynamic Global Illumination&lt;/em&gt;, &lt;em&gt;Open Problems in Real-Time Rendering&lt;/em&gt;, &lt;a href=&quot;https://jo.dreggn.org/path-tracing-in-production/2019/index.html&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Path Tracing in Production&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, &lt;em&gt;Ray Tracing Gems 1.1&lt;/em&gt;, and &lt;a href=&quot;https://sites.google.com/view/myfavoritesamples&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;My Favorite Samples&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Graphics</category><category>Event</category></item><item><title>Intuition Behind X86 &quot;lea&quot; Instruction</title><link>https://lesleylai.info/en/lea</link><guid isPermaLink="true">https://lesleylai.info/en/lea</guid><description>During the last meeting of the North Denver C++ Meetup, some people mentioned that lea is more confusing than other instructions. lea is an acronym for “load effective address.” The usual explanation is “to put a memory address from the source into the destination.” The syntax of lea in the Intel Sy..</description><pubDate>Tue, 11 Jun 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;During the &lt;a href=&quot;https://www.meetup.com/North-Denver-Metro-C-Meetup/events/261292867/&quot; target=&quot;_blank&quot;&gt;last meeting&lt;span&gt;&lt;/span&gt;&lt;/a&gt; of the North Denver C++ Meetup, some people mentioned that &lt;code&gt;lea&lt;/code&gt; is more confusing than other instructions. &lt;code&gt;lea&lt;/code&gt; is an acronym for “load effective address.” The usual explanation is “to put a memory address from the source into the destination.” The syntax of &lt;code&gt;lea&lt;/code&gt; in the Intel Syntax is the following:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;lea&lt;/span&gt;&lt;span&gt; destination, source&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For example, if you have an array &lt;code&gt;points&lt;/code&gt; of &lt;code&gt;struct Point&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; Point&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; x;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; y;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; z;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The compiler may generate the following line for &lt;code&gt;int x = points[i].y;&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;mov&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span&gt;, [&lt;/span&gt;&lt;span&gt;rbx&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;rcx&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt; + &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In this case, the register &lt;code&gt;rbx&lt;/code&gt; points to the array &lt;code&gt;points&lt;/code&gt;, &lt;code&gt;rcx&lt;/code&gt; is the index variable &lt;code&gt;i&lt;/code&gt;, and &lt;code&gt;eax&lt;/code&gt; is the register that holds &lt;code&gt;x&lt;/code&gt;. Similarly, for &lt;code&gt;int* x = &amp;amp;points[i].y;&lt;/code&gt;, compilers can generate&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;lea&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span&gt;, [&lt;/span&gt;&lt;span&gt;rbx&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;rcx&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt; + &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;However, besides using it for address operations, compilers seem to prefer using &lt;code&gt;lea&lt;/code&gt; to other arithmetic instructions as well for efficiency reason. For example, &lt;code&gt;int y = x * 5;&lt;/code&gt; may generate&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;lea&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span&gt;, [&lt;/span&gt;&lt;span&gt;rdi&lt;/span&gt;&lt;span&gt; + &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;rdi&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;instead of the more intuitive version of&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;imul&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span&gt;, [&lt;/span&gt;&lt;span&gt;rdi&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;lea&lt;/code&gt; is, in my point of view, a process of pointer arithmetic sandwiched with casts. For the previous example, the equivalent c code is&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;)(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)x)[x]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above code first treats &lt;code&gt;x&lt;/code&gt; as an &lt;code&gt;int&lt;/code&gt; pointer (&lt;code&gt;(int*)x&lt;/code&gt;), and then get address the &lt;code&gt;x&lt;/code&gt;-th element of that pointer. That part is essentially the address &lt;code&gt;[rdi + 4*rdi]&lt;/code&gt;. Next, it assigns the lower 32 bits of the address as an integer value to the destination.&lt;/p&gt;
&lt;p&gt;I hope this example gives you some intuitive understanding about &lt;code&gt;lea&lt;/code&gt;. Of course, no sane C programmer will write such kind of code by hand. The above code is not even conforming C++ for a good reason (C++ disallow casting from pointer to smaller type &lt;code&gt;int&lt;/code&gt;). However, from a machine’s perspective, such kind of “reinterpret_cast” is essentially a no-op, and machine languages leverage that all the time.&lt;/p&gt;</content:encoded><category>C</category><category>Coding</category><category>X86</category></item><item><title>When does a C++ temporary object die?</title><link>https://lesleylai.info/en/temporaries</link><guid isPermaLink="true">https://lesleylai.info/en/temporaries</guid><description>A lot of operations of C++ require temporary values. Using them before their destruction is imperative. However, not all C++ programmers I met have a solid understanding of when a temporary expire. This situation often leads to over-conservative estimations, which will not cause any harm. Neverthele..</description><pubDate>Thu, 28 Mar 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A lot of operations of C++ require temporary values. Using them before their destruction is imperative. However, not all C++ programmers I met have a solid understanding of when a temporary expire. This situation often leads to over-conservative estimations, which will not cause any harm. Nevertheless, sometimes it will cause programmers to assume guarantees that the language does not provide, which leads to insidious bugs.&lt;/p&gt;
&lt;p&gt;One of the common scenarios such problem manifest is when we manipulate a string with &lt;code&gt;std::string&lt;/code&gt;, but feed the result string back to an API that takes &lt;code&gt;const char*&lt;/code&gt;. Consider the following code snippet:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Hello, &quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; name &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;!&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string name{&lt;/span&gt;&lt;span&gt;&quot;Lesley Lai&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;puts&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(name).&lt;/span&gt;&lt;span&gt;c_str&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;span&gt; // highlight-line&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The C++ Standard guarantees it to work. The Standard mandates that all temporary objects get destroyed as the last step of evaluating of the &lt;strong&gt;full-expression&lt;/strong&gt; that contains the point where the temporaries were created&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. “full expression” means an expression that is not sub-expression of other expressions.&lt;/p&gt;
&lt;p&gt;A noteworthy exception of the rule is references. References can extend the lifetime of temporaries, but they will be a topic of another post.&lt;/p&gt;
&lt;p&gt;In “The Design and Evolution of C++,” Bjarne discussed the early design decision of the lifetime of temporaries &lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. The book refers to an earlier paper that identified several alternative destruction points. For example, in the original CFront implementation of C++, temporaries are destroyed at the end of the blocks. This approach caused problems when creating large temporaries, and some programmers explicitly avoided the issue by wrapping statements in curly braces.&lt;/p&gt;
&lt;p&gt;Another approach is to kill temporaries after the first use. An over-paranoid C++ programmer may suspect that the above code leads to undefined behavior. Having this thought may imply a subconscious assumption of this approach. I perceive this strategy more intuitive than the current way because of its consistency. With the current strategy, changing the above code a little bit will introduce undefined behavior:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;nodiscard&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Hello, &quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; name &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;!&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string name{&lt;/span&gt;&lt;span&gt;&quot;Lesley Lai&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// highlight-start&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; greeting &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(name).&lt;/span&gt;&lt;span&gt;c_str&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;puts&lt;/span&gt;&lt;span&gt;(greeting);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// highlight-end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the above code, the destructor of the temporary returned by &lt;code&gt;greet&lt;/code&gt; gets called after evaluating the full-expression. Thus, the pointer &lt;code&gt;greeting&lt;/code&gt; gets dangled. I got bite by expired temporary strings when dealing with OpenGL shaders before. Such code may even &lt;em&gt;appear&lt;/em&gt; to work for some cases &lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; because of &lt;em&gt;Small String Optimization&lt;/em&gt;. Anyway, if an undefined behavior &lt;em&gt;guarantee&lt;/em&gt; to break the program in a certain way, it is no longer undefined.&lt;/p&gt;
&lt;p&gt;Why C++ choose the current way? First, C++ cannot afford a garbage collection runtime, so “after the last usage” is out of the picture. Also, the current approach is far less error-prone to newbies than “after first use” strategy, while still performant without weird workarounds that “at the end of the block” implies.&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/language/lifetime&quot; target=&quot;_blank&quot;&gt;cppreference: lifetime&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D&amp;amp;E, 6.3.2 &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;for instance, in your unit tests &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>C++</category><category>Coding</category></item><item><title>C++ Lambda Tutorial</title><link>https://lesleylai.info/en/cpp-lambda</link><guid isPermaLink="true">https://lesleylai.info/en/cpp-lambda</guid><description>C++ lambda expression is a construct added to C++ back in C++11, and it continues to evolve in each version of the C++ standard. A core part of the language nowadays, lambda expressions enable programmers to express anonymous functions and closures in C++. This post describes what a lambda expressio..</description><pubDate>Mon, 25 Mar 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;C++ lambda expression is a construct added to C++ back in C++11, and it continues to evolve in each version of the C++ standard. A core part of the language nowadays, lambda expressions enable programmers to express anonymous functions and closures in C++. This post describes what a lambda expression is, provides some basic usages, and outlines their benefits.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#basic-usage&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Basic Usage&lt;/h2&gt;
&lt;p&gt;Passing functions as a parameter to customize the behavior of functions is a common task in programming. For example, since the conception of &lt;a href=&quot;https://en.cppreference.com/w/cpp/algorithm&quot; target=&quot;_blank&quot;&gt;standard algorithms library&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, a lot of the algorithms in the &lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt; can take an invokable entity as a callback. However, before C++11, the only kinds of invokable entities in C++ are function pointers and function objects. Both of them require quite a bit of boilerplate, and this cumbersomeness even impedes the adaption of the standard algorithm library in practice.&lt;/p&gt;
&lt;p&gt;In the meantime, lots of programming languages support features of &lt;a href=&quot;https://en.wikipedia.org/wiki/Anonymous_function&quot; target=&quot;_blank&quot;&gt;anonymous functions&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Before C++11, such features are mimicked by metaprogramming. For example, the Boost C++ library provided its &lt;a href=&quot;http://www.boost.org/libs/lambda&quot; target=&quot;_blank&quot;&gt;boost.lambda&lt;span&gt;&lt;/span&gt;&lt;/a&gt; library. Those metaprogramming hacks are slow to compile and some of the has performance implications at runtime; moreover, they require more boilerplate then one want. Thus, in C++11, lambda expressions are added as a language extension. As an example, the ISO C++ Standard shows usage of a lambda expression as a comparator of the &lt;code&gt;sort&lt;/code&gt; algorithm: &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;abssort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;unsigned&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(x, x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; n,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[](&lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(b));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Inside the function &lt;code&gt;abssort&lt;/code&gt;, we passed an instance of a lambda expression into &lt;code&gt;std::sort&lt;/code&gt; as a comparator. We can write a normal function to achieve the same purpose:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;abs_less&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(b));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;abssort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;unsigned&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(x, x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; n, abs_less);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If you are familiar with lambda expressions in other languages, everything should make sense except the mysterious &lt;code&gt;[]&lt;/code&gt; syntax. And that is our next topic.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#captures&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Captures&lt;/h2&gt;
&lt;p&gt;The above example shows the basic usage of lambda expressions, but lambda expressions can do more. The main difference between a lambda expression and a regular function is that it can “capture” state, and then we can use the captured value inside the lambda body. For example, the below function copies elements, which are above the threshold, from the old vector to the new vector.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Get a new vector&amp;lt;int&amp;gt; with element above a certain number in the old vector&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;filter_above&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threshold&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;copy_if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(v), &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(v),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;back_insert_iterator&lt;/span&gt;&lt;span&gt;(result),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;threshold&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; threshold;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// filter_above(std::vector&amp;lt;int&amp;gt;{0, 1, 2, 4, 8, 16, 32}, 5) == std::vector&amp;lt;int&amp;gt;{8, 16, 32}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above code captures &lt;code&gt;threshold&lt;/code&gt; by value. The &lt;code&gt;[]&lt;/code&gt; construct is called a &lt;em&gt;capture clause&lt;/em&gt;. There are two kinds of captures, capture by value or capture by reference (&lt;code&gt;[&amp;amp;]&lt;/code&gt;). For example, &lt;code&gt;[x, &amp;amp;y]&lt;/code&gt; - capture &lt;code&gt;x&lt;/code&gt; by value and &lt;code&gt;y&lt;/code&gt; by a reference. You can also have a default capture clause: &lt;code&gt;[=]&lt;/code&gt; captures everything in the current environment by value and &lt;code&gt;[&amp;amp;]&lt;/code&gt; captures everything by reference.&lt;/p&gt;
&lt;p&gt;We call a function that stores an environment a &lt;a href=&quot;https://en.wikipedia.org/wiki/Closure_(computer_programming)&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;closure&lt;/em&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;; almost all modern programming languages support closures. However, in all languages that I know except C++, the capture lists are implicit. In those languages, a closure captures all the bindings from the current environment.&lt;/p&gt;
&lt;p&gt;We can mimic the behaviors in those languages by capturing everything by reference (&lt;code&gt;[&amp;amp;]&lt;/code&gt;); it only captures variables in the environment that the lambda uses. However, default capture can be dangerous in C++; if the lambda lives longer than the captured object, then dandling problems occur. For example, we can pass a callback to asynchronous functions and capture resources by reference.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greeter&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string name{&lt;/span&gt;&lt;span&gt;&quot;Lesley&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;](){&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::cout &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Hello &quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; name &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The above code is undefined behavior since &lt;code&gt;name&lt;/code&gt; may be destroyed when we execute the asynchronous operation. The rule of thumb is only to use default capture by reference when the lambda is short-lived. For example, when passing a lambda to STL algorithms.&lt;/p&gt;
&lt;p&gt;The implicit capture strategy works in garbage-collected languages. &lt;a href=&quot;https://www.rust-lang.org/&quot; target=&quot;_blank&quot;&gt;Rust&lt;span&gt;&lt;/span&gt;&lt;/a&gt; gets away with implicit capture because of its borrow checker. On the contrary, by requiring the programmer to be explicit about ownership, the C++ approach provides more flexibility than the counterparts in other programming languages.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#lambda-expression-under-the-hood&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Lambda expression under the hood&lt;/h2&gt;
&lt;p&gt;We discussed quite a lot of usage of lambda so far. However, curious readers may start to wonder, what &lt;em&gt;exactly&lt;/em&gt; is a C++ lambda expression? Is it a primitive language construct like closures in functional languages? Before I talk about the internal of lambda, I will first talk about a construct date back to the C++98 era, &lt;strong&gt;function objects&lt;/strong&gt;.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;Some C++ programmers call the function objects “functors.” It is a misnomer that we should avoid. In &lt;a href=&quot;https://en.wikipedia.org/wiki/Category_theory&quot; target=&quot;_blank&quot;&gt;category theory&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, a functor is a map between categories&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;” and satisfy specific “functor laws.”&lt;/p&gt;
&lt;p&gt;Functional programming languages utilized this concept for their language constructs, though they too overloaded this terminology. In &lt;a href=&quot;https://en.wikipedia.org/wiki/Standard_ML&quot; target=&quot;_blank&quot;&gt;Standard ML&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/OCaml&quot; target=&quot;_blank&quot;&gt;OCaml&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, a functor is a higher-order module. You can think of it as a meta-function that maps a module to another module. A more prevalent usage comes from Haskell and various inspired languages and libraries, where functor is a type class that defines mapping operation. The Haskell definition of a functor is also useful in C++. For example, the standard &lt;a href=&quot;https://en.cppreference.com/w/cpp/ranges#Range_adaptors&quot; target=&quot;_blank&quot;&gt;range adaptors&lt;span&gt;&lt;/span&gt;&lt;/a&gt; can be considered functors that map ranges. Also, if the types &lt;code&gt;std::optional&lt;/code&gt; and&lt;code&gt;expected&lt;/code&gt; support a “map” operations, then they become functors. Various libraries already implemented that, and some standard proposals are working in this direction &lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3&gt;&lt;a href=&quot;#function-object&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Function Object&lt;/h3&gt;
&lt;p&gt;Function objects are normal objects that are able to be invoked. They are implemented by overloading a class’s &lt;code&gt;operator()&lt;/code&gt; operator. Below is our &lt;code&gt;abs_less&lt;/code&gt; example as a function object:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;abs_less&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;double&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(b));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;abssort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;unsigned&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(x, x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; n, abs_less{});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Function objects are more flexible than regular functions because they can store data like ordinary objects. Let us implement the previous &lt;code&gt;filter_above&lt;/code&gt; example with function object:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;typename&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GreaterThan&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;explicit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GreaterThan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threshold&lt;/span&gt;&lt;span&gt;): &lt;/span&gt;&lt;span&gt;threshold_&lt;/span&gt;&lt;span&gt;{threshold} {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;noexcept&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; other &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; threshold_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;T threshold_;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;filter_above&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threshold&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;copy_if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(v), &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(v), &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;back_insert_iterator&lt;/span&gt;&lt;span&gt;(result), GreaterThan{threshold});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;I am using &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/class_template_argument_deduction&quot; target=&quot;_blank&quot;&gt;Class template argument deduction (CTAD)&lt;span&gt;&lt;/span&gt;&lt;/a&gt; in this snippet. CTAD is a C++17 feature. In the previous versions, we need to write &lt;code&gt;GreaterThan&amp;lt;int&amp;gt;{threshold}&lt;/code&gt; with the template parameter &lt;code&gt;int&lt;/code&gt; specified.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3&gt;&lt;a href=&quot;#going-back-to-lambda-expressions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Going back to lambda expressions&lt;/h3&gt;
&lt;p&gt;Lambda expressions in C++ are syntactic sugars of those classes with &lt;code&gt;operator()&lt;/code&gt; defined.
At runtime, those lambda expressions get evaluated into function objects. Through the amazing &lt;a href=&quot;https://cppinsights.io/&quot; target=&quot;_blank&quot;&gt;C++ Insights&lt;span&gt;&lt;/span&gt;&lt;/a&gt; website, we can see a desugared version of our &lt;code&gt;abssort&lt;/code&gt; example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;abssort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;unsigned&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__lambda_6_9&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt; /*constexpr */&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;abs&lt;/span&gt;&lt;span&gt;(b));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(x, x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; n, __lambda_6_9{});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As you can see, a lambda expression creates a default constructed object of a &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/class#Local_classes&quot; target=&quot;_blank&quot;&gt;local class&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. Thus, C++ lambda expressions can do a lot of stuff anonymous functions in other languages may not allow to do. For example, you can inherit from lambda and have mutable states from lambda. Though I haven’t found too much use for either of them.&lt;/p&gt;
&lt;p&gt;The compilers generate the types of lambdas expressions; however, there is no way to use such types by their name through any standard means in a program. Nonetheless, type inferences and template works normally for those types. Also, we can use those types explicitly by &lt;code&gt;decltype&lt;/code&gt;. Below is an example from the &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/decltype&quot; target=&quot;_blank&quot;&gt;cppreference&lt;span&gt;&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; f &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [](&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; b;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;decltype&lt;/span&gt;&lt;span&gt;(f) g &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; f;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Such anonymous types are called “&lt;em&gt;Voldemort’s types&lt;/em&gt;” in the world of C++ and the &lt;a href=&quot;https://dlang.org/&quot; target=&quot;_blank&quot;&gt;D programming language&lt;span&gt;&lt;/span&gt;&lt;/a&gt; because they cannot be directly named, but codes can still use this type.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#capture-with-an-initializer&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Capture with an initializer&lt;/h2&gt;
&lt;p&gt;Now you understand a lambda expression is a syntactic sugar over classes; you may expect lambda expressions to store arbitrary values, not just to capture the values from their local scope. Fortunately, in C++14, lambda expressions can introduce new variables in its body by the mean of capturing with an &lt;em&gt;initializer&lt;/em&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]{ &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; x;&lt;/span&gt;&lt;span&gt; /* 1 */&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3&gt;&lt;a href=&quot;#move-capture&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Move capture&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.rust-lang.org/&quot; target=&quot;_blank&quot;&gt;Rust&lt;span&gt;&lt;/span&gt;&lt;/a&gt; closures can take ownership of the values in the environment. C++ lambda expressions do not have special support for such &lt;em&gt;move capture&lt;/em&gt;, but the generalized capture in the C++14 covers such use case:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// a unique_ptr is move-only&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; u &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;make_unique&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;some_type&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;some, parameters&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// move the unique_ptr into the lambda&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;go&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;( [&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;move&lt;/span&gt;&lt;span&gt;(u)] {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;do_something_with&lt;/span&gt;&lt;span&gt;(u);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#immediately-invoked-lambda-expression&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Immediately Invoked Lambda Expression&lt;/h2&gt;
&lt;p&gt;You can invoke a lambda expressions at the same place where we construct them.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[]() { &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;puts&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span&gt;); }();&lt;/span&gt;&lt;span&gt; // Same as what is inside the curly braces&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the world of Javascript, immediately invoked function expressions are all over the place since JavaScript programmers sometimes use them to introduce scopes. C++ does not need this kind of trickery. As a result, C++ programmers are more reluctant to use immediately invoked lambda. For example, in her &lt;a href=&quot;https://www.youtube.com/watch?v=n0Ak6xtVXno&quot; target=&quot;_blank&quot;&gt;talk&lt;span&gt;&lt;/span&gt;&lt;/a&gt; during CppCon 2018, Kate Gregory concerns about the readability of the immediately invoked lambda expressions for people not familiar with this idiom.&lt;/p&gt;
&lt;p&gt;Nevertheless, if you follow the best practice of declaring as more &lt;code&gt;const&lt;/code&gt; values as possible, immediately invoked lambda expression does provide an advantage. Some objects require complex construction beyond the constructor’s capability. Mutations will only happen during the construction of objects. Once the construction is completed, the objects will never be modified again. If such construction is reusable, then writing builder classes or factory functions is a sensible choice. However, if such construction only happens once in the codebase, a lot of the people will drop the &lt;code&gt;const&lt;/code&gt; qualifier instead. For example, consider that if you want to read several lines from &lt;code&gt;stdin&lt;/code&gt; into a vector:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; lines;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string line;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getline&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::cin, line);) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;lines&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push_back&lt;/span&gt;&lt;span&gt;(line);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It seems no way to make &lt;code&gt;lines&lt;/code&gt; constant since we need to modify it in the loop. Immediately invoked lambda expression solves this dilemma. With it, you can have both &lt;code&gt;const&lt;/code&gt; and no boilerplates:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; lines &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; lines;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string line;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getline&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::cin, line);) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;lines&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push_back&lt;/span&gt;&lt;span&gt;(line);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; lines;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;section&gt;&lt;h2&gt;&lt;a href=&quot;#footnote-label&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;See &lt;a href=&quot;http://eel.is/c%2B%2Bdraft/expr.prim.lambda#1&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;[expr.prim.lambda]&lt;/strong&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Functor&quot; target=&quot;_blank&quot;&gt;Wikipedia: Functor&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;See &lt;a href=&quot;https://wg21.link/p0798&quot; target=&quot;_blank&quot;&gt;p0798R3: Monadic operations for std::optional&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://isocpp.org/wiki/faq/cpp14-language#lambda-captures&quot; target=&quot;_blank&quot;&gt;C++14 Language Extensions: Generalized lambda captures&lt;span&gt;&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>C++</category><category>Coding</category></item><item><title>Book Review: &quot;Functional Programming in C++&quot;</title><link>https://lesleylai.info/en/functional-cpp</link><guid isPermaLink="true">https://lesleylai.info/en/functional-cpp</guid><description>Functional Programming in C++ by Ivan Čukić is a new book about applying functional programming principles in C++. This book is for people who already have a decent understanding of C++. It is written in an idiomatic style that a C++ programmer should feel welcome.



If you just start to learn C++,..</description><pubDate>Fri, 22 Mar 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://www.manning.com/books/functional-programming-in-c-plus-plus&quot; target=&quot;_blank&quot;&gt;Functional Programming in C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/em&gt; by Ivan Čukić is a new book about applying functional programming principles in C++. This book is for people who already have a decent understanding of C++. It is written in an idiomatic style that a C++ programmer should feel welcome.&lt;/p&gt;
&lt;div&gt;&lt;img src=&quot;/_astro/book_cover.BtP6104-_NHinB.webp&quot; alt=&quot;Functional Programming in C++ Book Cover&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;375&quot; /&gt;&lt;/div&gt;
&lt;p&gt;If you just start to learn C++, this book may not be the best starting point. I will recommend &lt;a href=&quot;http://www.stroustrup.com/tour2.html&quot; target=&quot;_blank&quot;&gt;A Tour of C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt; instead. On the other hand, the book does not require any functional programming knowledge. The book spends its first six chapters to build basic functional programming concepts like pure functions, higher order functions, partial applications.&lt;/p&gt;
&lt;p&gt;As a programmer already familiar with FP, the book does not provide too much major revelation to me. However, I still gain some small insight from each chapter. Though the implementation from this book may not be sophisticated and efficient, they demonstrate concepts pretty well because of their simplicity.&lt;/p&gt;
&lt;p&gt;Chapter 6 discusses lazy evaluations and memoization. I feel like the book’s implementation for memoization is too inefficient to be useful, though I cannot come up with a better solution myself. I fear that a generic yet efficient solution is hard to find, and memoization should more be implemented in a case by case basis. Nonetheless, I particularly like the later part of lazy string concatenation by using expression templates.&lt;/p&gt;
&lt;p&gt;Chapter 7 introduces &lt;a href=&quot;https://en.cppreference.com/w/cpp/ranges&quot; target=&quot;_blank&quot;&gt;ranges&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, which are merged into C++20 already. The introduction is not in depth, but it is necessary since later chapter uses ranges extensively. Chapter 8 discussed persistence data structures. The &lt;a href=&quot;https://github.com/arximboldi/immer&quot; target=&quot;_blank&quot;&gt;immer&lt;span&gt;&lt;/span&gt;&lt;/a&gt; C++ library is an robust implementation of those structures. The library’s &lt;a href=&quot;https://www.youtube.com/watch?v=sPhpelUfu8Q&quot; target=&quot;_blank&quot;&gt;CppCon talk&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://public.sinusoid.es/misc/immer/immer-icfp17.pdf&quot; target=&quot;_blank&quot;&gt;ICFP paper&lt;span&gt;&lt;/span&gt;&lt;/a&gt; are also fantastic resources to learn more.&lt;/p&gt;
&lt;p&gt;Chapter 10 is about functors and monads. This chapter connects constructs like ranges, &lt;code&gt;std::future&lt;/code&gt;, &lt;code&gt;std::optional&lt;/code&gt;, and &lt;code&gt;expected&lt;/code&gt; into more general concepts. Unlike a lot of “monad tutorial” online, the book takes a more practical approach. A normal imperative programmer should easily understand the material if they followed all the previous chapters. I am; however, not impressed by his usage of the range-based &lt;a href=&quot;https://en.wikipedia.org/wiki/Pythagorean_triple&quot; target=&quot;_blank&quot;&gt;Pythagorean triple&lt;span&gt;&lt;/span&gt;&lt;/a&gt; example, especially with the readability and performance concern such code &lt;a href=&quot;https://aras-p.info/blog/2018/12/28/Modern-C-Lamentations/&quot; target=&quot;_blank&quot;&gt;raises&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Chapter 11 talks about template meta-programming. It considers type traits as “meta-functions” operates on the type-level. The class template trick to he mentioned to debug metaprogramming is helpful, and I hope that I know it earlier. One of &lt;a href=&quot;https://cukic.co/2019/02/19/tmp-testing-and-debugging-templates/&quot; target=&quot;_blank&quot;&gt;Ivan’s blog posts&lt;span&gt;&lt;/span&gt;&lt;/a&gt; provides more techniques for debugging template code.&lt;/p&gt;
&lt;p&gt;Chapter 12 details on concurrent systems and provides a functional reactive solution. It puts all the ideas in the book into a practical, real-world scenario.&lt;/p&gt;
&lt;p&gt;Overall, I will recommend all C++ programmers who are curious about terms like “Currying,” “Monad,” and “Lazy Evaluation” to read this book. Functional programming becomes popular nowadays. Thus, you will find more C++ codebases written in various degree of functional styles. Reading this book can help you understand, write, and appreciate such codebases.&lt;/p&gt;</content:encoded><category>Books</category><category>Coding</category><category>C++</category><category>FP</category></item><item><title>Tail Recursion Explanation</title><link>https://lesleylai.info/en/tail-recursion</link><guid isPermaLink="true">https://lesleylai.info/en/tail-recursion</guid><description>Tail-recursion is an important concept to understand before we can analyse the behavior of a functional program. I will try to illustrate what tail recursion is with an Elm-like pseudocode. Though you don’t need to know any Elm to understand this post.


FROM RECURSION TO TAIL-RECURSION

Consider th..</description><pubDate>Tue, 22 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Tail_call&quot; target=&quot;_blank&quot;&gt;Tail-recursion&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is an important concept to understand before we can analyse the behavior of a functional program. I will try to illustrate what tail recursion is with an &lt;a href=&quot;https://elm-lang.org/&quot; target=&quot;_blank&quot;&gt;Elm&lt;span&gt;&lt;/span&gt;&lt;/a&gt;-like pseudocode. Though you don’t need to know any Elm to understand this post.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#from-recursion-to-tail-recursion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;From recursion to tail-recursion&lt;/h2&gt;
&lt;p&gt;Consider the following function:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if &lt;/span&gt;&lt;span&gt;n &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;then &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;else &lt;/span&gt;&lt;span&gt;n &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; factorial(n &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We can expand &lt;code&gt;factorial(4)&lt;/code&gt; as&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;factorial(4)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= if (4 == 0) 1 else 4 * factorial(4 - 1)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= 4 * factorial(4 - 1)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= 4 * factorial(3)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= 4 * (if (3 == 0) 1 else 3 * factorial(3 - 1))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= 4 * 3 * factorial(2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= 4 * 3 * 2 * 1 * 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;= 24&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Because we multiply numbers to the inner-function call result, we need a place to store those numbers 4, 3, 2, 1. Those numbers are stored in the &lt;strong&gt;stack frames&lt;/strong&gt;. Since every function has its own frame, we need to create n + 1 stack frames for &lt;code&gt;factorial(n)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Tail recursion is a space optimization for the recursive calls. Unlike most optimizations, it changes the asymptotic behavior of the memory usage from  to . The idea is that if a recursive call itself is the last action in another function call, the function’s stack frame can be reused. Function calls in the tail position of another function call are called tail call.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#accumulators---technique-for-implement-tail-recursive-functions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Accumulators - Technique for implement tail recursive functions&lt;/h2&gt;
&lt;p&gt;A nice technique to transform naive recursive functions to tail recursive counterparts is using accumulators. For example, here is a tail recursive version of &lt;code&gt;factorial&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let &lt;/span&gt;&lt;span&gt;helper acc n &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if &lt;/span&gt;&lt;span&gt;n &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;then &lt;/span&gt;&lt;span&gt;acc &lt;/span&gt;&lt;span&gt;else &lt;/span&gt;&lt;span&gt;helper (acc &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; n) (n &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;helper &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Using accumulators implies an iterative process that we use all the times with loops. Indeed, tail recursions will always transform into the same kind of low-level code as the loops by a compiler.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#continuation-passing-style&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Continuation-passing style&lt;/h2&gt;
&lt;p&gt;Accumulators are not always working. There is another technique called &lt;a href=&quot;https://en.wikipedia.org/wiki/Continuation-passing_style&quot; target=&quot;_blank&quot;&gt;continuation-passing style&lt;span&gt;&lt;/span&gt;&lt;/a&gt; (abbreviate as CPS) to transform more complex recursive functions. Here is our &lt;code&gt;factorial()&lt;/code&gt; function in continuation-passing style:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial_k&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial_k&lt;/span&gt;&lt;span&gt; n k &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if &lt;/span&gt;&lt;span&gt;n &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;k(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;factorial_k (n &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;span&gt;v &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; k(v &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; n))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;factorial&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;factorial_k n (&lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; x)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As you see, there is a lot of boilerplate with no apparent benefit. Writing code in CPS manually is tedious and error-prone, so it is probably not worthwhile to code every recursive function in CPS style. On the other hand, there are tools to translate normal functions into CPS.&lt;/p&gt;
&lt;p&gt;Note that the Elm compiler cannot compile code like this at all and would generate infinite recursion at the time of writing, but you can try this function in some other languages.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;#afterthought&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Afterthought&lt;/h2&gt;
&lt;p&gt;Since tail recursion is an optimization, not all implementations of all programming language will implement them. For example, there is no mandatory tail-call elimination in the C++ Standard at the time of writing, though all the mainstream compilers (MSVC, Clang, and GCC) will do it anyway. The story is different in functional programming languages. Those languages usually will mandate tail-call elimination if you write a tail-recursive function. The reason is that those languages usually discourage loop or have no loop at all, so tail-call elimination is necessary to achieve a decent performance in a lot of cases. To be a good citizen in those languages, you should try to write recursive functions tail-recursive (at least on the easy cases where you can transform them with accumulators.)&lt;/p&gt;</content:encoded><category>FP</category><category>Coding</category><category>Elm</category></item><item><title>Book Review: &quot;Professional CMake: A Practical Guide&quot;</title><link>https://lesleylai.info/en/professional-cmake</link><guid isPermaLink="true">https://lesleylai.info/en/professional-cmake</guid><description>CMake is the de facto industry standard for the build system generator of the C and C++ this days. Like C++, people seem to love and hate it at the same time. However, it is definitely a better choice compare to writting Makefiles manually.

There are a bunch of Cmake resources online, in the forms ..</description><pubDate>Tue, 15 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://cmake.org/&quot; target=&quot;_blank&quot;&gt;CMake&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is the de facto industry standard for the build system generator of the C and C++ this days. Like C++, people seem to love and hate it at the same time. However, it is definitely a better choice compare to writting Makefiles manually.&lt;/p&gt;
&lt;p&gt;There are a bunch of Cmake resources online, in the forms of youtube videos, conference talks, and blog posts, but they are usually either for beginners, solve a specific problem, or focus on “best practices.” I would not say such resources are bad, but they are inadequate. For example, even though books like &lt;a href=&quot;https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996&quot; target=&quot;_blank&quot;&gt;Effective Modern C++&lt;span&gt;&lt;/span&gt;&lt;/a&gt; are useful, but we need to first read books like &lt;a href=&quot;https://www.amazon.com/C-Programming-Language-4th/dp/0321563840&quot; target=&quot;_blank&quot;&gt;The C++ Programming Language&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to have the whole picture of the C++ language. And counterparts of this book in the CMake world are hard to find.&lt;/p&gt;
&lt;p&gt;As a result, CMake is always a dark side to my codebase. I use CMake for years with a very shallow understanding of how it functions. For most of the time, my level of familiarity with CMake is enough. I would copy and paste code snippets I find online. However, whenever I want to do any “non-trivial” tasks with CMake, I will meet trouble. One of the reasons is that a lot of tutorial writers, like me, have a minimal understanding of CMake so that they will post none-robust CMake scripts. For instance, a lot of the times we need to copy resources files from the source directory to the binary directory, and for years I used a way that would only copy files when a file with the same name does not exist in the build directory. Nonetheless, in Graphics programming, I modify shaders all the time, and every time I need to delete the files in binary directory manually. A more sinister drawback of this workflow is that I can modify the shaders and forget to remove the old ones.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Professional CMake Front Cover&quot; loading=&quot;lazy&quot; width=&quot;794&quot; height=&quot;1123&quot; src=&quot;/_astro/front-cover.Ly3wU-gP_17lBGM.webp&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Recently, I find someone recommend “Professional CMake: A Practical Guide,” a CMake handbook written by a CMake co-maintainer &lt;a href=&quot;https://crascit.com/&quot; target=&quot;_blank&quot;&gt;Craig Scott&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. The book is a structured introduction to CMake. It helps me to form a basic understanding of how CMake works. I learned concepts like differences between configure time and generate time and generator expressions. All of those are rarely mentioned in online tutorials. The book also mentions a lot of “best practices” and the common pitfalls of using CMake in each chapter (and the better alternatives).&lt;/p&gt;
&lt;p&gt;All in all, I recommend this book for anyone kept using CMake in the dark. Build system codes are still part of the production system, and they deserve the same attention as the regular codes. Maybe you should treat them even more carefully than the regular codes since in a lot of times build system errors are even harder to debug than the most insidious template metaprogramming bugs (Afterall, CMake scripts are “meta-meta programming” in a very dynamic language where no type system will save you.)&lt;/p&gt;</content:encoded><category>Books</category><category>CMake</category><category>Coding</category></item><item><title>Resource management and RAII in C++</title><link>https://lesleylai.info/en/raii</link><guid isPermaLink="true">https://lesleylai.info/en/raii</guid><description>Recently, I have encountered a legacy code base at work. There are several tremendous class written like this:



The real class is much bigger. We can criticize this snippet in multiple ways. For example, the copy-operations will do shallow copy, which is counter-intuitive. And programmers of the d..</description><pubDate>Wed, 26 Oct 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, I have encountered a legacy code base at work. There are several tremendous class written like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExtnlOutData&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; phase;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt; phaseIdx;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;&lt;span&gt; phaseNames;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ExtnlDLLData&lt;/span&gt;&lt;span&gt;() : &lt;/span&gt;&lt;span&gt;phaseIdx&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;phaseNames&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;) {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;~ExtnlDLLData&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (phaseIdx) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;delete[]&lt;/span&gt;&lt;span&gt; phaseIdx;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;phaseIdx &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (phaseNames) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; phase; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;i) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;phaseNames&lt;/span&gt;&lt;span&gt;[i]) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;delete[]&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;phaseNames&lt;/span&gt;&lt;span&gt;[i];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;delete[]&lt;/span&gt;&lt;span&gt; phaseNames;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;phaseNames &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The real class is much bigger. We can criticize this snippet in multiple ways. For example, the copy-operations will do shallow copy, which is counter-intuitive. And programmers of the dynamic libraries conform this interface need to allocate memory themselves, which is monotonous and error-prone. If we allocate more space to &lt;code&gt;phaseIdx&lt;/code&gt; than &lt;code&gt;sizeof(int) * phase&lt;/code&gt;, memory leak happens; if we allocate less space, the program will crash mysteriously.&lt;/p&gt;
&lt;p&gt;I want to focus on the “DLL” part today. This class is designed as an interface for customized plug-ins of our software. We use them like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calculate&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ExtnlOutData data;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;extnlDllCalculate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;data);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Do something about data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The problem is that now all parts of our software need to be compiled by the same compiler which builds legacy shared libraries (In our case, it is Visual Studio 2008, which is quite ancient). The reason is that we destroy memory outside the dll while allocate memory inside the dynamic libraries. Since different compilers may call different memory management functions, the program will crash at the destructor of &lt;code&gt;data&lt;/code&gt;. This situation is like what happens when we combine &lt;code&gt;malloc()&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt;, but it is a lot more insidious.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#qt-library-example&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Qt library: example&lt;/h3&gt;
&lt;p&gt;It is surprised to me that some otherwise well-designed code bases suffer similar problem. For instance, the &lt;a href=&quot;http://www.qt-project.org&quot; target=&quot;_blank&quot;&gt;Qt Library&lt;span&gt;&lt;/span&gt;&lt;/a&gt;’s parent-child relationship is a similar resource management strategy. If you have used QT, you must have written code like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Not real Qt code&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;QString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;QFont&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;font&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTabWidget parent;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; child &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; QWidget;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addTab&lt;/span&gt;&lt;span&gt;(child);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setName&lt;/span&gt;&lt;span&gt;(name);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setFont&lt;/span&gt;&lt;span&gt;(font);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; // The distructor of parent will destory child&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As a consequence, Qt, unlike most libraries, cannot be linked by different compilers than what itself compiled. For example, QT 5.7.0 for windows 64 binaries have three versions (VS 2015, VS 2013, MinGW) to satisfy different compiler users. We must use corresponding compilers to develop Qt application.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;#exception-safety-problem&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Exception safety problem&lt;/h3&gt;
&lt;p&gt;If you are programmers develop software solely for POSIX platforms, you may think it is not your business. But I have another point relate to you, too. The point is, those &lt;em&gt;ad hoc&lt;/em&gt; resource management strategies are innately exception-unsafe. Consider what will happen if &lt;code&gt;setName&lt;/code&gt; or &lt;code&gt;setFont&lt;/code&gt; can throw exceptions. An innocuous order change by clients will introduce leak:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;setName&lt;/span&gt;&lt;span&gt;(name);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;setFont&lt;/span&gt;&lt;span&gt;(font);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// if the above lines throw, the child will never be freed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;addTab&lt;/span&gt;&lt;span&gt;(child);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No wonder old style libraries like QT forbid exceptions for “historical reasons”. But the library authors still cannot prohibit clients do something like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;setName&lt;/span&gt;&lt;span&gt;(name);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;setFont&lt;/span&gt;&lt;span&gt;(font);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;valid&lt;/span&gt;&lt;span&gt;()) &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; Exception{&lt;/span&gt;&lt;span&gt;&quot;Invalid tab&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;span&gt; // May cause leak&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;addTab&lt;/span&gt;&lt;span&gt;(child);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#raii-to-rescue&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;RAII to rescue&lt;/h2&gt;
&lt;p&gt;In the title, I discourage you from inventing your own resource management routine. The reason is c++ already have a standard resource management idiom &lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot; target=&quot;_blank&quot;&gt;RAII&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. It can easily eradicate problems about leak and unmatched system functions memtioned above. We can redesign the first example like below:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PhaseData&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; ID;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::string name;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExternalOutData&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;private:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;PhaseData&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; data;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As for the GUI example, if you decide to write a new GUI library now, you can design your interface like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;MyString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;MyFont&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;font&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;MyTabWidget parent;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; child &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;make_unique&lt;/span&gt;&lt;span&gt;(MyWidget);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setName&lt;/span&gt;&lt;span&gt;(name);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setFont&lt;/span&gt;&lt;span&gt;(font);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addTab&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;move&lt;/span&gt;&lt;span&gt;(child));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; // The distructor of parent will destory child&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This version is a bit more verbose, but it has the similar usage of Qt, without Qt’s problems.&lt;/p&gt;</content:encoded><category>C++</category><category>Coding</category><category>Opinion</category></item><item><title>Integrate a unit test framework in cmake</title><link>https://lesleylai.info/en/unit-test-with-cmake</link><guid isPermaLink="true">https://lesleylai.info/en/unit-test-with-cmake</guid><description>Automatic tests are ubiquitous in software industry these days. Especially to large-scale software, it is necessary to have a set of test to ensure the specification is fulfilled and to prevent regression bugs. In this post, I will not bore you with why we do test. Instead, if you are using the CMak..</description><pubDate>Fri, 13 May 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Automatic tests are ubiquitous in software industry these days. Especially to large-scale software, it is necessary to have a set of test to ensure the specification is fulfilled and to prevent regression bugs. In this post, I will not bore you with why we do test. Instead, if you are using the &lt;a href=&quot;https://cmake.org/&quot; target=&quot;_blank&quot;&gt;CMake&lt;span&gt;&lt;/span&gt;&lt;/a&gt; build system, I will show you how easy it is to integrate test into the system.&lt;/p&gt;
&lt;p&gt;In this tutorial, my directory structure includes two parts: the sources (in &lt;code&gt;src&lt;/code&gt; subfolder) and tests (in &lt;code&gt;test&lt;/code&gt; subfolder).&lt;/p&gt;
&lt;p&gt;The test framework I chose is &lt;a href=&quot;https://github.com/philsquared/Catch&quot; target=&quot;_blank&quot;&gt;Catch2&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. However, the process of using different frameworks like CppUnit, Boost Test Library, doctest, or googletest should be very similar.&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#setup&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Setup&lt;/h1&gt;
&lt;p&gt;Firstly, I added all the source code except &lt;code&gt;main.cpp&lt;/code&gt; into a library called &lt;code&gt;common&lt;/code&gt; and linked it by both the production program and the test.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;./CMakeLists.txt&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cmake_minimum_required&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;VERSION&lt;/span&gt;&lt;span&gt; 2.8)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt; (MyAwesomeProject)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_subdirectory&lt;/span&gt;&lt;span&gt; (src)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_executable&lt;/span&gt;&lt;span&gt;(MyAwesomeProject src/main.cpp)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;target_link_libraries&lt;/span&gt;&lt;span&gt; (MyAwesomeProject common)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_subdirectory&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;src/CMakeLists.txt&lt;/code&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_library&lt;/span&gt;&lt;span&gt; (common a.hpp a.cpp b.hpp)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h1&gt;&lt;a href=&quot;#configure-test-framework&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Configure test framework&lt;/h1&gt;
&lt;p&gt;We can create a &lt;code&gt;test/CMakeLists.txt&lt;/code&gt; that deals with testing stuff. You can then put the unit test library into your repository. Since Catch is a header-only library, we can use CMake’s &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries&quot; target=&quot;_blank&quot;&gt;interface library&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to handle it. For libraries like googletest, just link it as a normal library.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Add catch as an interface library&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(CATCH_INCLUDE_DIR &amp;lt;WHERE YOUR Catch.hpp is&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_library&lt;/span&gt;&lt;span&gt;(Catch &lt;/span&gt;&lt;span&gt;INTERFACE&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;target_include_directories&lt;/span&gt;&lt;span&gt;(Catch &lt;/span&gt;&lt;span&gt;INTERFACE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${CATCH_INCLUDE_DIR}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Add test executable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_executable&lt;/span&gt;&lt;span&gt; (tests testmain.cpp testA.cpp testB.cpp)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;target_link_libraries&lt;/span&gt;&lt;span&gt;(tests Catch CommonSourceCode)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#an-alternative-cmake-external-project&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;An alternative: CMake external project&lt;/h2&gt;
&lt;p&gt;An (unrecommended) alternative is to fetch the test framework from GitHub automatically and configured it as a CMake &lt;a href=&quot;https://cmake.org/cmake/help/latest/module/ExternalProject.html&quot; target=&quot;_blank&quot;&gt;external project&lt;span&gt;&lt;/span&gt;&lt;/a&gt;. This way you do not need to worry about updating the test framework to its latest version. Do aware this way you cannot compile the code without Internet connection since whenever CMake runs it will try to fetch your unit test framework online.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt;(ExternalProject)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;find_package&lt;/span&gt;&lt;span&gt;(Git REQUIRED)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ExternalProject_Add(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PREFIX&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${CMAKE_BINARY_DIR}&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;/catch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;GIT_REPOSITORY https://github.com/philsquared/Catch.git&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;TIMEOUT&lt;/span&gt;&lt;span&gt; 10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;UPDATE_COMMAND &lt;/span&gt;&lt;span&gt;${GIT_EXECUTABLE}&lt;/span&gt;&lt;span&gt; pull&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CONFIGURE_COMMAND &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BUILD_COMMAND&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;INSTALL_COMMAND &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;LOG_DOWNLOAD &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Expose required variable (CATCH_INCLUDE_DIR) to parent scope&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ExternalProject_Get_Property(catch source_dir)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(CATCH_INCLUDE_DIR &lt;/span&gt;&lt;span&gt;${source_dir}&lt;/span&gt;&lt;span&gt;/include &lt;/span&gt;&lt;span&gt;CACHE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;INTERNAL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Path to include folder for Catch&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Add catch as an interface library&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_library&lt;/span&gt;&lt;span&gt;(Catch &lt;/span&gt;&lt;span&gt;INTERFACE&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;target_include_directories&lt;/span&gt;&lt;span&gt;(Catch &lt;/span&gt;&lt;span&gt;INTERFACE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${CATCH_INCLUDE_DIR}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Add test executable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_executable&lt;/span&gt;&lt;span&gt; (tests testmain.cpp testA.cpp testB.cpp)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;target_link_libraries&lt;/span&gt;&lt;span&gt;(tests Catch CommonSourceCode)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#ctest-support&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;code&gt;ctest&lt;/code&gt; support&lt;/h2&gt;
&lt;p&gt;Now we can run the test program manually by executing the test executable. We can even configure our IDE to run the test excutable whenever we compile.&lt;/p&gt;
&lt;p&gt;Still, we can do better. &lt;a href=&quot;https://cmake.org/cmake/help/latest/manual/ctest.1.html&quot; target=&quot;_blank&quot;&gt;CTest&lt;span&gt;&lt;/span&gt;&lt;/a&gt; is the test driver program that CMake provides. To enable &lt;code&gt;ctest&lt;/code&gt;, we need CMake to realize our &lt;code&gt;tests&lt;/code&gt; executable is for tests.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;add_test&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NAME&lt;/span&gt;&lt;span&gt; tests &lt;/span&gt;&lt;span&gt;COMMAND&lt;/span&gt;&lt;span&gt; tests)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;enable_testing&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;To enable &lt;code&gt;CTest&lt;/code&gt;, add the following line into the top level CMakeLists file after we define the project.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt;(CTest)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2&gt;&lt;a href=&quot;#package-managers&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Package managers&lt;/h2&gt;
&lt;p&gt;If your project use package managers like &lt;a href=&quot;https://conan.io/&quot; target=&quot;_blank&quot;&gt;Conan&lt;span&gt;&lt;/span&gt;&lt;/a&gt; or &lt;a href=&quot;https://docs.hunter.sh/en/latest/index.html&quot; target=&quot;_blank&quot;&gt;hunter&lt;span&gt;&lt;/span&gt;&lt;/a&gt;, integrating unit test frameworks should be brainless. However, the idea of making a test executable alongside the main one still apply.&lt;/p&gt;
&lt;h1&gt;&lt;a href=&quot;#conclusion&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;CMake is a widely accepted cross-platform build tool across the industry. Adding unit test and other supporting tools like &lt;a href=&quot;https://en.wikipedia.org/wiki/Continuous_integration&quot; target=&quot;_blank&quot;&gt;CI&lt;span&gt;&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Static_program_analysis&quot; target=&quot;_blank&quot;&gt;static analysers&lt;span&gt;&lt;/span&gt;&lt;/a&gt; to it is incredibly easy.&lt;/p&gt;
&lt;p&gt;If you are still using IDE specific configurations or good old Makefiles for C or C++ projects, I will suggest you spend several hours learning how to use CMake. It will be a production boost.&lt;/p&gt;</content:encoded><category>CMake</category><category>Coding</category><category>C++</category><category>Testing</category></item></channel></rss>