Libraries aren't implementing it. There's no `cargo`-like tooling for installing modules (AFAIK).
Can the C++ committee revert or refine the modules spec? Has anything like that been done before?
Another example is the GC introduced in C++11, likewise no one made use of it.
VC++, clang and GCC have implemented modules, granted there are still bugs to iron out.
I just wish we'd get working, well-supported modules like that for C++. I tried them once, but support was abysmal and I won't touch them again until they work nicely everywhere.
Nowadays, with exception of header units, VC++ and clang alongside MSBuild and CMake/ninja are pretty much usable for anyone that is able to stick to a specific platform.
I don't consider still fighting with build tools options in 2025 to make a pleothora of npm dependencies happy to run under nodejs a minor issue.
As always, the problems are always with 3rd party libraries that require special handling when compiling, but that was always the case.
We could have off-the-shelf tooling as good as Cargo etc today, if it weren't for those special cases. Myself I just use a simple script.
I'm not sure what you mean here. Could you explain please?
For example, if we use libraries A and B and both want to define module "foo", straightforward compiler options passed when compiling their sources could make the undisciplined libraries produce instead, in the context of our project, modules fooA and fooB and accordingly consume fooA or fooB (found in our project's module stash) where they reference their own module "foo", as if the replacement names had been used in export and import clauses.
Are module names completely erased from actually compiled libraries and executables? What complications am I missing?
I'm not being facetious. It's a design choice. Many languages don't but Java and C# for example require modules to have globally unique fully qualified names.
Maybe this was the intention of the C++ committee. C++ does support hierarchical module names so Java style naming is possible. If everyone adopts it then name clashes won't be a problem.
For example, without assuming wrong names on the part of third party developers, a project could compile multiple variants of the same library with the intent of segregating multiple copies of the same symbols (e.g. buried in other libraries as transitive dependencies, in different dynamic link libraries that are selected at runtime, in executable variants that are compiled collectively for convenience).
This would be manageable with explicitly controlled object and library file names, but ambiguous if linking is funneled through ambiguously named modules.
But as you say, this doesn't solve the problem of including multiple versions of the same module.
The solution that Java has for that is literally re-writing the bytecode of version A to be "in a different module" and re-writing the bytecode of the code that depends on version A to use the "new" module. That's not going to fly for C++ as I understand it, but maybe I'm missing something.
The inconvenience of handling a binary format should be much smaller than the challenge of parsing C++ sources to find names.
Globally unique namespace names are needed to be able to differentiate the same name used in multiple namespaces, but of course are potentially a problem if you don't have control over them.
It might occasionally be useful if there was a workaround to resolve namespace clashes by doing something like:
namespace foo {
#include "foo/module.h" // namespace Module
using Module; // Module.x is now foo.x
}
namespace bar {
#include bar/module.h" // namespace Module
using Module; // Module.x is now bar.x
}
Or, we could invent a new syntax like "import foo/module as foo".
But AFAIK there is no way to then tell the linker to rename symbols to match (e.g. -l foo/module.o as foo -l bar/module.o as bar).
Renaming symbols is done with objcopy. From objcopy(1):
--redefine-sym old=new
Change the name of a symbol old, to new. This can be useful when
one is trying link two things together for which you have no
source, and there are name collisions.Than modules were standardized and this happened in a very strange way. Usually major features are already implemented at least in some compilers before being standardized, but with modules it wasn't the case. It was in 2020, it's now 2025 and they aren't fully implemented and tested in all major compilers and it's unclear how long one need to wait to be able to use them.
Modules are also very problematic, as the article above shows. They didn't solve many C++ problems with multiple translation units management, like compilation speed. Moreover they added new problems atop of old ones. And managing dependencies may become ever more painful, because some dependencies use old-style includes and some use modules instead (xkcd 927).
>This is not a goal. Module files are essentially better PCH, they are not meant to be a stable artifact. Consumers compile the module files from the library's interface files as needed.
That's not what I was expecting (since I haven't looked into modules too carefully). Seems counterintuitive. Today I can download an external library's pre-built artifacts and link them as long as they are compiled with the same compiler family for my architecture, etc.
This seems to mean you can't import pre-compiled modules of such a library.
OTOH, for large game projects you also want to compile third-party libs from source at least once to make sure you don't end up in the wrong branch of the debug/release/x64/x86/DLL/static maze.
So maybe it's a non-issue for most projects. You get the code, compile it once and store the artifact for future use.
Still seems a bit restrictive to me. I would have expected modules to be like DLL/.so so you could use them at your own peril if you wanted to do something quick/dirty.
usrnm•4mo ago
juliangmp•4mo ago
1718627440•4mo ago
usrnm•4mo ago
1718627440•4mo ago
von_lohengramm•4mo ago
pjmlp•4mo ago
C++ modules support having templates with private code, compilers than retrieve what they need from the BMI (Binary Module Interface), like in any other module based language that supports binary libraries.
1718627440•4mo ago
I think what is the right approach is to make sure, that a header file really only contains the "public" API. Common definitions or static/inline functions should be better put into a separate *.c file that is then included in multiple translation units, but since it is separate from the real API, it can be included in much less other files. Some also use the convention to name this files *.inc or *.imp .
As for name conflicts, C has the tooling for this, as compilation and symbol handling are separate steps. It might not be the cleanest approach, but you can always bundle some translation units into a convenience library and apply a linker script, or strip symbols with objcopy.
Symbols names before compilation can be influenced with the preprocessor by naming a macro with the same name, which essentially renames the symbol. For the mentioned conflict of preprocessor names (aka. macros), I see no other way short of modifying the code or undefining/redefining. Most people also use a build system which can trivially call out to sed, before invoking the compiler.
usrnm•4mo ago
That's if a macro conflicts with another macro, the real fun begins when a macro conflicts with something else in your code, and suddenly a piece of your code gets transparently replaced with something completely different. Granted, in most cases the result won't compile and you'll just spend some time scratching your head and staring at bizarre error messages, but one day you might get especially lucky and it will compile. Good luck debugging that.
1718627440•4mo ago
jasode•4mo ago
It literally is a name conflict. It's not a DEBUGGER SYMBOL type of name conflict but it's still a name collision. A famous example of a macro name conflict is Microsoft windows.h ntdef.h min() max():
https://www.google.com/search?q=Microsoft+windows.h+min+max+...
The "windows.h" is not "incompatible" code. It just has a name conflict that needs a workaround.
1718627440•4mo ago
It sounds a bit like some people have poor macro hygiene. I thought it's standard to just undefine all macros immediately after use.
ziml77•4mo ago
magicalhippo•4mo ago
C++26 will get run-time reflection from what I can gather[1], in which case symbol names will matter after linking, no?
[1]: https://learnmoderncpp.com/2025/07/31/reflection-in-c26-p299...
theICEBeardk•4mo ago