Practical C++ Modules - Boris Kolpackov - CppCon 2019

preview_player
Показать описание



Modules are merged into the C++20 draft which means we now have a good idea what to expect, functionality-wise. Tooling support is also not far behind with compiler and build system vendors making steady progress. So we've got modules, but what now? How do we start using modules in our projects?

The aim of this talk is to answer the "What (& Why)", "How", and "When" of C++ Modules: what are modules (& why do we need them), how to apply them to new and existing codebases, as well as when can we start the migration.

We begin with a brief introduction to modules (structure, partitions, header units, include translation) and their relation to other physical design mechanisms (namespaces, headers, libraries, packages). We will also get a basic understanding of the underlying build mechanics which turns out to be necessary to use modules effectively.

Next we dive into the practical aspects of using modules: should we start with header units or go straight to proper modules? If header units, then should we use explicit import or rely on include translation? And if proper modules, then what is the appropriate module granularity? How to name our modules? Split or not to split (into module interface/implementation units)? And what about module distribution?

We conclude the talk by discussing the state of compilers, build systems, and (system) headers with regard to modules and whether now is a good time to start a new or modularize an existing project.

Boris Kolpackov
Code Synthesis
Chief Hacking Officer
South Africa

Boris Kolpackov is a founder and CHO (Chief Hacking Officer) at Code Synthesis, a company focusing on the development of open-source tools and libraries for C++. For the past 10 years Boris has been working on solving interesting problems in the context of C++ using domain-specific languages (DSL), C++ parsing, source-to-source translation, and code generation. His notable projects to date include ODB (ORM for C++), XSD and XSD/e (XML Schema to C++ compilers), as well as libstudxml (XML parser/serializer library for C++).


*-----*
*-----*
Рекомендации по теме
Комментарии
Автор

Oh, I remember some almost 20 years ago, when I started with C/C++, and I ran into "cyclic dependencies". A strange problem for a beginner.

antiHUMANDesigns
Автор

Glad to finally see a shell prompt with a distinct color rather than an all-green flow of text where we can't see where commands have been entered :)

retropaganda
Автор

A couple of points came to my mind while watching this talk:
1. How do modules help the problem of splitting the code between headers and source files if we split the code between interface and implementation module units?
2. How can we build better C++ integrations from other languages by parsing and consuming BMIs if the BMI is compiler-specific?

mariusbancila
Автор

I don't really understand when you're trying to represent headers as a disadvantages when you refer to DRY principle. So, you're saying that we have to repeat ourselves. Can you please show where we're repeating ourselves? Do you mean when we declare a function in a header, we should repeat the declaration of it in the source file as well?

davithov
Автор

@37:50, why would the importers of the no-split approach need to recompile when the implementation in a .mpp file changes? Is it just an assumption that the tooling wouldn't be implemented as smart enough to detect when a change to a .mpp file is only an implementation (and not an interface) change (in order to know that importers of the module don't need to be recompiled)? I assume that such a build tool optimization would be complicated/difficult to implement, but it isn't immediately obvious to me why it might be impossible. Is there a "deeper" technical limitation that prevents such an optimization?

I have _no idea_ what I'm talking about and I'm probably spouting nonsense, but here's my attempt to come up with an answer I might find somewhat satisfying: I suppose if a toolchain's BMI layout internally makes some kind of BMI dependency information position-dependent, and lays out the "interface bits" of a BMI in a way that is non-stable with repect to implementation-only changes, that would be a problem. Ex. b has b_function0, which uses a_function2 from a, and the bmi format is such that b.bmi says it can find the interface info of a_function2 at byte 0x123 of a.bmi, but the bytes representing the implementation of a_function0 and a_function1 are before 0x123, so if the implementation of a_function0 or a_function1, b would definitely need to recompile/update b.bmi to point to wherever a_function2's "interface bits"'s new offset in a.bmi is. And supposing that there was a good tradeoff-related reason that such a BMI layout/repreesntation was chosen, then I would find that understandable. I'm guessing it would be really borthsome for build-systems / build-system generators like CMake if different compiler toolchains varied in whether recompilation is needed in such a scenario if they really want to make the most of possible optimizations. Again, I have no idea what I'm talking about, I know it's probably way more complicated than that. I apologize for however much my ignorance has betrayed me (and maybe annoyed you) in writing the above. I'm just trying to give an example of the level of explanation I'm curious to get.

I suppose the same question goes for split hpp/cpp files- ie. "why does a simple change to a header like adding whitespace cause my build tooling to recompile all my cpp files that include that header?" I'm assuming the answer starts with something like: "it would be an absolute nightmare to implement correctly because... (reasons x y z (probably including something to do with preprocessing and macros and the complexity of parsing a programming language))", which I can appreciate. I'm happy enough that I get such powerful tools for free.

@50:57 I really appreciate that the discussion is tuned for different contexts. One of the things I find a little hard about reading / listening to guidelines or suggestions about how to write code is that sometimes the guideline is mostly only relevant to one such context, and the person giving the guideline sometimes doesn't make that clear.

davidfong
Автор

42:01 if modules aim to replace headers, why would it be a bad idea to make a module per class?

BGFutureBG
Автор

14:46 What is the b command run at the prompt? Is it an aliased bash script?

JohnWasinger
Автор

Guys it’s 2023 and nodules still buggy, gives Internal Compiler Error when used with std::string 👎 c++ is a joke now you can’t even finish 20 standard

rcom
Автор

Headers should be deprecated ASAP, its a prehistoric relict and its bad for both ease of use and performance.

ragnarlothbrok
Автор

I disagree with only one point: that modules solves compilation speed problem. 3-5x speed gain is almost nothing, compare what we could achieve with distributed compilation systems. And because modules almost remove ability for parallel compilation (you may not see it with 8 threads, but it is obvious like for 200 compilation threads) it is a step back in terms of speed.
Despite that fact, I totatally for modules, as they bring useful abstraction and incapsulation.

mapron