Idiomatic C++ module use

119 Views Asked by At

I am thinking about using modules in my new project so I have looked at https://github.com/infiniflow/infinity/tree/main as it was recommended to me as a modern project that uses modules.

I was surprised that they pretty much just use modules as header files as I thought the whole point of modules was to get rid of them and just have a single implementation file.

Is this project using modules in a weird way or is this what modules are supposed to be?

1

There are 1 best solutions below

0
Nicol Bolas On

It isn't the way you would probably organize a project that you were writing from scratch with modules. However, from the history of that project, it was "refactored" into using modules, so presumably the intent was to be minimally disruptive. So header files became individual module files to ease user transitioning into the system.

One trap that this project fell into was its use of many very simple module names. Module names are global; they don't have any namespacing support. And you cannot include two projects that create modules that are named the same. Even if the name is only used internally.

So you would never be able to use this project with some other project that uses the module name function, even if neither of them exports that module name. Most of the modules this project uses should have been module partitions, not actual modules (or, failing that, at least use some kind of project_prefix.name for the name of these internal sub-modules) . Partition names within a module cannot conflict with partition names from some other module (this is why partitions exist).

So no, this project does not exhibit good practices.

the whole point of modules was to get rid of them and just have a single implementation file

If you're talking about the conceptual distinction between headers and source files (interface vs. implementation), no, even the earliest version of the current module proposal had a distinction here.

Virtually every C++ build system rebuilds files based on file modification timestamps. If you modify a file, then the build system assumes everything dependent on that file is going to have to be modified. So if you modify a file that defines a module being imported by something else, that something else needs to get recompiled. Even if the modification you made isn't one that changed the module in a way that matters.

While a module-based build system might in theory attempt to avoid this, in practice it's extremely difficult to implement. What would have to happen is that the module gets rebuilt and compared with the previous compiled version of that module. If they didn't change, then there's no need to cascade that module rebuild into the included modules. It's easier to just let the file modification date handle things.

So if you want to limit the recompilation cascade resulting from modifying the implementation of a module, those files need to be separate from the interface units of a module.