4 ms·
In C++ modules globally unique module names seem to be unavoidable
- usrnm 1y agoIt doesn't really change much, name clashes are already an existing danger that can bite you at any moment you download somebody else's code from the Internet. Definitely not something unique to C++ modules and not an argument against them
- juliangmp 1y agoConflicts with symbol names are a thing yes, but if I use some open source library I don't have to care about how they named their translation units. Header files might clash, which is also bad design IMO, so the reasonable thing and what I've made my default is to have a subdirectory with the library name in the include path (I.e. inc/MyLib/foo.h instead of inc/foo.h).
- 1718627440 1y agoBut the symbol names don't matter after linking. I can happily reuse a symbol name for something different after the previous symbol has been linked and does not appear anymore in the exported symbol table.
- usrnm 1y agoThere are many, many ways to have a name conflict in C++. A lot of them don't even have anything to do with symbols or linking, like macro conflicts. And yes, they do happen, and they're not fun to debug.
- 1718627440 1y agoWhy do you put in foreign code (excluding declarations) in your translation unit? Isn't a translation unit under the control of a single party/vendor? And you can just undef them and the compiler gives a warning/error about the redefinition.
- von_lohengramm 1y agoThat might be the case in C land, but C++ land usually has a lot more stuff in headers. For examples, templates are not very useful unless they're defined in headers.
- pjmlp 1y agoC has similar issues with macros and _Generic. 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 1y agoYes, there can be problems. This can be counteracted by remembering that the file name does not make a header file. Having headers, i.e. forward declaration does make a C file a header file. They seams to be an aversion to include *.c files, but in my opinion doing the same in a *.h file makes the problem only worse. 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 1y ago> and the compiler gives a warning/error about the redefinition 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.
- ziml77 1y agoUsing a header file for kdb+ was great fun with its short macro and function names causing all sorts of weird breaks.
- magicalhippo 1y ago> But the symbol names don't matter after linking. 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-p2996/ https://learnmoderncpp.com/2025/07/31/reflection-in-c26-p299...
- theICEBeardk 1y agoNo it is gaining compile time reflection. But RTTI has been a thing for a long time.
- dlivingston 1y agoC++ modules seem like one of those things worth staying far, far away from. I wish they worked well because it would be a huge boon to modernizing C++. But from what I've seen, it's a dumpster fire. The spec is too broad and ill-defined. The compilers have gone to herculean lengths to implement it regardless, and MSVC is the only compiler with full support (for a C++20 feature, mind you). [0] 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? [0]: https://arewemodulesyet.org/tools/ https://arewemodulesyet.org/tools/
- cjfd 1y agoYes, reverting has happened. extern templates have been removed.
- m-schuetz 1y agoIn JS, modules were a massive improvement pretty much from day one. They were fairly quickly adoped and worked well. It's been a huge quality-of-life improvement, especially with the latter addition of import maps. 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.
- pjmlp 1y agoTo be fair, only thanks to JavaScript/TypeScript compilation and polyfills to AMD and CJS pseudo modules approach, only recently has nodejs supported ES6 modules without having to deal with switches.
- HelloNurse 1y agoIf names must be unique, shouldn't there be a way to resolve conflicts by renaming the modules? 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?
- masfuerte 1y agoIf names must be unique you don't need to rename them because they are unique. 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.
- HelloNurse 1y ago"Everyone" is an awful lot of people. In practice, there will be conflicts and there must be a good plan for handling them. Editing third party source code to change names is not a good plan. 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.
- masfuerte 1y agoGlobal uniqueness works in Java. Modules are named with the organisation's DNS name in reverse (guaranteed unique) plus the module name or whatever additional structure you want. So Microsoft's evil module might be `com.microsoft.evil` or `com.microsoft.marketing.web.evil`. But as you say, this doesn't solve the problem of including multiple versions of the same module.
- HarHarVeryFunny 1y agoIMO module names should be the same as the namespace of objects exported by the module (more like Modula-2). I've never used C++20, but modules do seem a bit of a mess. 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).
- 1718627440 1y ago> 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.
- Panzerschrek 1y agoIt seems for me that adding modules into C++ was a mistake. The old-style approach with includes wasn't ideal, but it was well understood and all its downsides and pitfalls were well known. 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).
- muststopmyths 1y agoFrom comments in the blog post >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.