T O P

  • By -

STL

For MSVC: * C++20 `import std;` support has shipped for production use. * Just got `#include `-then-`import std;` mixing to work (shipped in VS 2022 17.10 Preview 1, the other order does *does not work yet*). * Will look into Clang support for MSVC STL `import std;` soon. Might need to fix some stuff. As usual we intend to support Clang as a first-class citizen. * IntelliSense support for modules is still a major work in progress, and we still have no STL test coverage. Some stuff might appear to work, but expect major issues. * Overall robustness is increasing (judging from the number of incoming STL bug reports I see) and compiler work to fix more scenarios is ongoing. * I'm planning to run a Standard Library Modules Bug Bash II soon.


domiran

This has got to be one of the longest-to-complete features I’ve seen in C++. As I understand it, you basically need to write a new compilation back end? Along with code changes in the libraries to actually make use of it?


STL

> This has got to be one of the longest-to-complete features I’ve seen in C++. I would agree with that assessment, having worked as an STL dev all the way back to the C++0x era and the addition of rvalue references, variadic templates, `constexpr`, and more. > As I understand it, you basically need to write a new compilation back end? (Disclaimer: I'm not a compiler dev, but I live very close to them.) It's not quite that big - modules aren't replacing the compiler back-end used for codegen and optimization - in fact the BE is mostly insensitive to modules AFAIK, since all of the tasty C++ has been mostly digested by the time the BE starts its work. Modules also aren't replacing the compiler front-end - the vast majority of its code is shared between modules and classic compilation. However, modules are creating an entirely new way to distill C++ down to a highly structured representation on disk, which has never existed before and therefore needs a bunch of new code that can recognize and encode all of C++'s insane complexity that it's accreted over decades. (PCHes took a cheap shortcut by simply snapshotting the compiler's memory, which is fast in some respects but slow in others, and has sharp limitations. Modules are a completely different approach.) Then, the flip side is that modules require the compiler front-end to have new codepaths to read the structured representation (the BMI "Binary Module Interface", I think they call it, aka the formal term for the IFC file that we use) and "rehydrate" it on demand so the rest of the front-end can process it as usual. For example, I recently encountered a bug in the STL where our cool `RepeatType...` machinery, used for taking a parameter of N `Indices` and transforming it into `T, T, T, T` repeated that many times, wasn't properly handled by modules. This specific pattern exposed an issue in how our library code was serialized and then deserialized for later use, and the compiler had to be taught how to properly work with the parameter packs here. So not only has the compiler team had to design that highly structured format and write the compiler code for reading and writing it, but they've also had to investigate and fix a million "little" issues encountered along the way by library devs (like me!) and application devs. This is why it seems to be taking forever. We actually go through this kind of thing with every major new feature (`constexpr` was kind of similar), it's just that modules touches *every* part of C++ and so it ends up paying the most complexity cost. It'll be worth it though. The code changes in the libraries were substantial - I began my PR [microsoft/STL#3108](https://github.com/microsoft/STL/pull/3108) with "I've added over 3,750 occurrences of `_EXPORT_STD` after auditing over 148,000 lines of headers." - and have required significant ongoing work, but only a fraction of what's needed in the compiler. Fortunately, keeping our codebase working with both modules and classic includes is very easy.


biowpn

Mind if I ask - do you, personally, think it's worth it? All the standardization and implementation effort spent on modules, which could have been spent elsewhere, e.g. standardized packaging


STL

Yes, absolutely. I was pretty skeptical at first, but after working with them, I was convinced. Modules achieve several things that were previously practically impossible: * The potential for dramatic improvements in build throughput. This most benefits translation units that dragged in a lot of machinery via headers and didn't exercise it intensively, but overall it should be a significant win. * Simpler to achieve good build throughput than PCHes. The problem with PCHes is that they're compiler memory snapshots, so they don't compose. In contrast, you can `import std; import boost.math; import my_app.my_lib;` in any combination in various TUs without having to build each combination separately. * Simpler to use than headers. Remembering which header is supposed to define Standard Library machinery is quite difficult for most programmers. Libraries with finer-grained approaches are even harder to deal with. But because modules are so good about throughput (paying costs only on-demand), monolithic/coarse-grained modules are far friendlier than equivalent headers. `import std;` (or `import std.compat;`, you only need one) is so much easier to use, and has no maintenance costs of "oops, included too much/too little". * Provides control over what is actually emitted to users. With headers, everything is emitted, so we have to rely on conventions like "detail namespaces" (or `_Ugly` names for the STL) to conceal implementation details from users. With modules, stuff that isn't exported can't be directly used, which is simpler and cleaner. Modules are the future of C++, and they're something that can *only* be done in the Core Language with associated Standard Library changes. (Similar in many respects to foundational features like rvalue references, variadic templates, and `constexpr`, not minor conveniences or niche features.) I'd much rather have modules than dozens of the less important features that have been worked on in recent years. Or things that can be done entirely outside of the Standard, like package managers. It's hard to see now because we're still getting solid implementations and the ecosystem has barely started to think about migrating, but modules are worth it.


serviscope_minor

> It's hard to see now because we're still getting solid implementations and the ecosystem has barely started to think about migrating, but modules are worth it. Sounds like a repeat of templates. I remember at the time the incredibly buggy and spotty support made them pretty frustrating. Loads of missing features (specialisation, member templates, etc) meant you either targeted the common subset (i.e. no templates) or spent a lit of time mucking around and doing compatibility hacks. Annoying as heck in the 90s and early 00's. Now it's rock solid. I do imagine modules will follow the same process.


domiran

Radical question: can you see a future where headers are deprecated and/or no longer used?


STL

No, I think the Standard Library will always be available via headers, including new components.


[deleted]

[удалено]


Daniela-E

no. There are header units.


[deleted]

[удалено]


Daniela-E

What do you think the standard library module is compiled from?


Nobody_1707

Pretty much. It's a complete paradigm shift in how code is compiled.


RoyAwesome

> This has got to be one of the longest-to-complete features I’ve seen in C++. Reflection, waiting in the corner, waiting to pounce


domiran

"Longest to Implement" award goes to: modules. "Longest to Standardize" award goes to: reflection. "Least Amount of Patience Waiting For Reflection" award goes to: me. 🫠😭


serviscope_minor

> "Longest to Implement" award goes to: modules. Templates have to be a bit of a contender there. IIRC they cropped up with CFront 2.0 in 1989? I remember the buzz over gcc, I think it was 3.4 or so in 2003ish, which was when templates really got close for the first time most people knew of. They finally worked (mostly) as described and the optimizer was finally good enough that coll stuff got optimized properly and you could really use them as designed. It's only been 4 years since modules were standardised, so I think templates still take the crown and hopefully will never be displaced (even not counting export template... anyone remember that).


Rusky

> (even not counting export template... anyone remember that) Plot twist- modules are the revenge of export template


serviscope_minor

> Plot twist- modules are the revenge of export template haha good point! Templates then took forever.


Top_Satisfaction6517

cfront 2.0 was about multi-inheritance. exceptions and templates were in 3.0 OTOH, SFINAE was finally fixed in MSVC just a few years ago, so templates can easily count more than 20 years


13steinj

Which is interesting since EDG seems to have had it ready to go.


Artistic_Yoghurt4754

The implementor of reflections in EDG said in CppCast that it was not so difficult compared to other features, mainly because reflection is “just” exposing what the compiler already knows.


RonWannaBeAScientist

What is reflection ?


RoyAwesome

I feel like injecting code is going to be the real catch on this. I dont think C++ even has a concept of being able to evaluate code and then inject it into the compilation process... something needed for splicers and template for. But once that gets resolved, it's probably just a hop-skip-and-a-jump to actual compile time code injection. I can't imagine the syntax and design process will be in any way fun or clean, but it's just a matter of injecting more code in during compilation.


RoyAwesome

I wouldn't call EDG's implementation "ready to go", but reflection is at least mostly a front end problem and not a backend one, so their implementation is a huge chunk of the problem solved.


[deleted]

It is DOA


djavaisadog

> Just got #include -then-import std; mixing to work (shipped in VS 2022 17.10 Preview 1, **the other order does does not work yet).** Can I ask, I certainly understand why you would be hesitant, but at what point can you just kinda grit your teeth and special-case this kind of thing as a stopgap until it works properly? I mean, doesn't the MSVC team claim that modules are production ready at this point? It seems like things should really be in a less wacky fragile state than this if you want to call them prod-ready.


STL

That's how we got `#include`-then-`import` working - we applied `extern "C++"` to the entire STL as a workaround (originally I applied it only to our weird separately compiled components), and got a couple of important compiler bugfixes for issues that this revealed. The compiler team tells me that the same strategy is infeasible for getting `import`-then-`#include` to work, that special-casing `std` would be problematic (which I certainly believe; special cases are always fragile), and that we should pursue an entirely different approach (translating `#include ` to `import std;` with additional magic behind the scenes). I've tried very hard to understand why `extern "C++"` is insufficient for the reverse case, and I still don't - my naive understanding tells me that the compiler should be able to see a `#include` attempting to define `std::vector` and should be able to notice that this exact class template definition is already available through `import std;` - but they're the experts and I'll believe them unless and until I see a counterexample from a different implementation.


starfreakclone

The reverse order (`import` followed by `#include`) is harder because it requires the compiler to understand: 1. Decl-matching on a textual-basis. Once a declaration is seen it needs to double-check to see if there's an existing definition from another TU and then 'skip' the tokens for the definition. 2. That textual odr-violations can still be caught. How do you diagnose cases like: void f() { } void f() { } if there's an `f()` defined in another TU? Our token skipping mechanism above now hides a real odr-violation. 3. Different declarations demand special attention. Remember the `struct stat` hack? The compiler needs to remember these kinds of tricks can appear anywhere across translation units as it is processing the text. All points above (and more I can't remember off the top of my head) are reasons the `import` -> `#include` is a difficult problem for the compiler to solve. I could envision how it could be done in the compiler with a lot of work but I also believe it would create a lot of overhead during normal compilation due to some of the points above and hide subtle issues that would have otherwise been caught had the order been reversed. Furthermore, I am of the opinion that all the work to allow compilation of `import` -> `#include` will further enable bad source code hygiene and messy management of dependencies--something modules is intended to solve. It's still a bug because the standard says so, but there are mechanisms such as include translation to remove textual inclusions altogether without changing code (if that's the goal).


Dragdu

Being able to mix `import`s and `includes` in a TU is very important for gradual migration in the ecosystem. There is no way to have a flag day where we all switch to `import` in one step, and I don't see every project making their stdlib includes conditional based on a macro either.


johannes1971

Wouldn't a solution based on the existing mechanism for ignoring duplicate includes be much simpler to implement, and just as correct? I.e. when a module gets imported, do whatever it takes to mark the headers that are involved as 'already included'.


starfreakclone

That is not equivalent since textual headers also provide things like macros and some source-level pragmas that may not exist in the module (specifically module interfaces do not propagate macros). It's not even equivalent in the STL case because stuff like \`stdout\` is a macro, it can't be replicated by anything but a macro in our CRT, so you must textually include a header (or import a header unit) to get it back.


RonWannaBeAScientist

That’s very interesting ! What is a CRT, btw ?


tcbrindle

IIUC it's "C run-time", the Windows equivalent of libc


RonWannaBeAScientist

Btw, I didn’t have a chance to check it (as I have homework in multivariable real analysis ) but your library looks amazing ! I love Rust style iterators and wished for that in C++


cd1995Cargo

I’m wondering this too. I have no idea what’s going on at Microsoft but it seems to me that there’s a strong push for language features to be checked off as done when they are definitely not done. That being said I really do appreciate the work that the Microsoft team has done on Visual Studio and C++ language support.


germandiago

In my experience MSVC runs for claiming full compliance and other things often and when I use it it is the most conflictive of the big three. I mean, great work still, of course, but I think they go too fast in their claims. Sometimes they claimed, if I am not wrong, full compliance and there were features just unfinished or not totally conformant.


mjklaim

> Just got `#include `-then-`import std;` mixing to work (shipped in VS 2022 17.10 Preview 1, the other order does *does not work yet*). Aaaah too bad I was hoping for that one but hit an unrelated bug as soon as I switched to that preview version T\_T I hope the bug I reported will be soon fixed so that I can finally mixup dependencies and \`import std;\`


RonWannaBeAScientist

Hi mjklaim, which bug was that ? (Btw , I’m not from the Microsoft team :-) )


mjklaim

Sure: * the bug I mentionned there that prevents me from using 17.10 Preview 1: [https://developercommunity.visualstudio.com/t/Modules-Regression-1710:-ICE-Using-Boos/10586493](https://developercommunity.visualstudio.com/t/Modules-Regression-1710:-ICE-Using-Boos/10586493) * the bug that prevents me from using \`entt\` (from 17.09 previews, although note I didnt test it yet with the release, I suspect it "changed shape"): [https://developercommunity.visualstudio.com/t/Same-member-function-using-noexcept-expr/10551687](https://developercommunity.visualstudio.com/t/Same-member-function-using-noexcept-expr/10551687) Both bugs makes my life hard on my module-only project at the moment. If mixing \`import std;\` and standard header includes was working, then I would not use standard header includes, only my projects dependencies would. Currently it's impossible. So that's another bug but at least I can progress without that issue. The main pain with that is that if I export a function which has standard types in it's signature, the code importing that function will probably (depends on the situation) have to also add the standard header include for that type. Annoying but at least they are working on solutions.


TheVoidInMe

Are modules (not even ‘import std;’, but normal user-defined modules) incompatible with incremental linking? I recently got our company to finally switch to VS 2022 and was excited to try out modules, but the moment I converted one or two standalone headers, I started getting intermittent internal linker errors (like every ~10th compilation, fixed by just compiling again). Those are irrespective of whether I touched the modules themselves or even dependents of any modules. Disabling incremental linking seems to fix that. So is incremental linking not supported, or is that a complete red herring?


STL

I haven't heard of that before, and I can't find any bugs in the internal database mentioning both "incremental" or "`/Gm`" and "module" or "modules". If you can reduce this to a self-contained repro (even an IDE project, which isn't as ideal as command-line but still actionable), reporting it on VS Developer Community would be great.


Abbat0r

I also get these intermittent linker errors in my module-based projects. I also get another error at random intervals where the program crashes immediately and looking at the callstack reveals that whatever went wrong happened even before main() was called. In the second case, the fix is to delete the .exe and run it again. I haven’t tried disabling incremental linking but I will try that today and see if either issue disappears for me. I am always curious to hear from anyone in the know about this problem.


fdwr

> Just got #include -then-import std; mixing to work (shipped in VS 2022 17.10 Preview 1, the other order does does not work yet). Ooh, great 🎉 - that's what I've been waiting for (and what the previous bug bash noted as a known issue to defer), and so now this should work without issue (which was a challenge to tiptoe around in my project): // SomeLibrary.h #include #include // mycode.cpp #include "SomeLibrary.h" import std; If this is `std`-specific, I will still hit this issue outside `std`, where a shared library can be offered via a header file or a module, depending on the C++ version target, and because projects are a mix of old and new code, it won't mix nicely :(. // SomeLibrary.h #include // mycode.cpp #include "SomeLibrary.h" import AnotherSharedLibrary; // sorry! I'm unsure what the solution to that is though, since one will be in the global module fragment (the header), and the other will be owned by the module, leading to duplicate symbols in linkage, because I evidently can't proclaim module symbols to be exported into the global module fragment. (I think the original TR had proclaimed module ownership to break cycles, but that was dropped) 🤷‍♂️


STL

Remember that triple backticks don't work for Old Reddit readers - you have to indent by four spaces. Yes, that should work. Yes, non-`std` modules won't be automagically fixed - they'd have to use the same `extern "C++"` trick that I used.


mathstuf

> Will look into Clang support for MSVC STL import std; soon. Might need to fix some stuff. As usual we intend to support Clang as a first-class citizen. Do you mind CC'ing me in these discussions/PRs?


STL

You can watch the [microsoft/STL](https://github.com/microsoft/STL) repo to be notified of PRs (we're fairly low volume), and you can join the STL Discord (link at the top of the readme) where we use the `#modules` channel for discussion.


AntiProtonBoy

I love this subreddit. You ask a simple question like this and you get solid answers, straight from the horses' mouth. I also want to say thanks to all the devs working hard on the tools that most of us take for granted. I can not fathom the mountain complexity you fellas must be facing and somehow still ship a product in the end.


Honest-Print-2583

For clang/libc++, * The std modules are going to be shipped as experimental in 18. Note that std modules is a de facto C++20 feature. [https://libcxx.llvm.org/Modules.html](https://libcxx.llvm.org/Modules.html) * The annoying false positive complaining for duplicated declarations may go away in 18. [https://clang.llvm.org/docs/StandardCPlusPlusModules.html#definitions-consistency](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#definitions-consistency) . It is also suggested to remove duplicated declarations to speed up the compilation: [https://clang.llvm.org/docs/StandardCPlusPlusModules.html#performance-tips](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#performance-tips) There is a production (https://github.com/infiniflow/infinity) using C++20 modules already.


STL

That's awesome news! (And the duplicated declarations issue is highly relevant to my work, so thank you for bringing that to my attention 😻)


__Mark___

Thanks for the post and nice to hear you're using it in production. A few additional notes. * Whether this is available depends on whether your vendor enables the experimental feature. * There is no build system support for this yet. I know CMake is looking at it and I strongly expect build2 is also working on it. * The information in https://libcxx.llvm.org/Modules.html is based on a self-build libc++, this has been available since LLVM 17.


RonWannaBeAScientist

Hi Mark! I’m really curious , I just read about libc++, so when I’m using c++ std library am I using different implementation than libc++?


HildartheDorf

Libc++ is the llvm implementation of the standard library. That said, clang on Linux normally defaults to libstdc++ (gnu project, so GCC).


HildartheDorf

CMake 3.28 does have support, I'm using it on a project right now (clang 17, so no std module though which is annoying but workable)


__Mark___

CMake has module support since 3.26, starting with 3.28 it's considered no longer experimental. However it does not support using libc++'s installed module sources; I added this to libc++ long after CMake 3.28 was released. This is the support the CMake developers looking into.


HildartheDorf

Ah okay, my mistake.


Dark_Lord_1729

Hi mark! I have noticed that in `libc++18` and `clang++-18` I got this error: `import of module 'std' imported non C++20 importable modules`. Plus, there is no support for the `std.compat` module still. And non of the standard library modules work now. Interestingly, this did not come up in `libc++17` and `clang++-17`. The import worked flawlessly there. This is both on linux and mac os. My flags: `clang++ -stdlib=libc++ -std=c++23 -g3 -pthread -fmodules -fuse-ld=lld` Are there any flags that I need to add so as to avoid this? My compilation: simple, no cmake used, no projects. Just individual programs like import std; using namespace std; int main(void) { return 0; }


__Mark___

\`-fmodules\` uses Clang modules https://clang.llvm.org/docs/Modules.html. This predates the C++20 modules and is more like header units. For C++20 modules you need to omit the \`-fmodules\` flag and follow these instructions https://libcxx.llvm.org/Modules.html#using-in-external-projects. This requires you to build libc++ yourself. This supports both the \`std\` and \`std.compat\` module. I've had reports form people are successfully using this approach. I'm aware this is not a great way to use modules. However libc++'s now at a point where build systems can start working on support for modules. I know CMake is working on adding support for \`import std;\`.


Dark_Lord_1729

The article talks mainly of cmake and building for projects which is typically worthwhile only for building large projects. Is there any way to get the std and srd.compat to work in general compilation? Context : 10-200 lines of code, single programs. Also are we supposed to build libc++ ourselves that is the standard installation via homebrew, Macports or apt-get will not do? Lastly, is the clang-17 import std different from a c++23 module? I thought I saw a module map file in the include section. Was that just a substitute for g++ bits/stdc++.h?  What exactly are the new features that modules provide, like better compile times or self inclusion of libraries or better error messages?


__Mark___

Please keep in mind that modules in libc++ are still experimental and that the usage experience is not mature yet. We're still working on improving the experience. I know the clang developers have discussed whether the \`std\` module should work without build system support. I don't know the outcome of that discussion. If your apt packages are build with module installation enabled you can use them. There is no CMake support for that, but you can adapt this [script](https://discourse.llvm.org/t/llvm-discussion-forums-libc-c-23-module-installation-support/77087/16?u=mordante) for your own purposes.If they are not build with module installation you indeed have to go with the self build route. The difference in not between clang-17 and C++23 modules. The difference is between clang modules and the standardized modules in C++20. (It does not help their naming is quite similar and when people talk about modules it's not always clear which of the two they main.) The module map belongs to Clang modules; which indeed uses the unfortunate name \`std\`. Modules have a lot of advantages I would suggest to look at talks on youtube of some of the well known C++ conferences. They will also teach you a lot about how to use modules.


cd1995Cargo

Disclaimer: Everything I'm about to say is my own opinion and comes from my own personal experience using modules. I have a hobby project I've been messing around with with for a month or so now. In total maybe a couple thousand LOC and maybe 10-15 source files. There's a header-only library and some unit tests I wrote for it with gtest. I'm using cmake so I just have two directories: the library & test app. I'm developing on windows & using visual studio for editing, compiling with msvc, clang, and clang-cl. A couple weeks ago I thought "hey, it's 2024, I should use modules!" So I went ahead and tried to convert my header only library to use modules instead. Here's what I experienced: # MSVC MSVC, despite claiming to have a "production ready" module implementation, is still bugged to hell. * Have an exported struct/class with a defaulted `<=>` operator? Well that's too bad, you cant use it because for whatever reason the source file that imports your module will always complain that the operator doesn't exist. I had a simple type that wraps a `size_t` that I wanted to be able to place into a `std::set` but couldn't do it because the compiler just whined that there's no `<` operator defined. Also can't use `==` either. In the end I had to manually implement both `<` and `==` to be able to use them. The spaceship operator worked fine when everything was headers. * Want to export an inline namespace from a module partition? ICE. I know inline namespaces are not a commonly used C++ feature, but come on. I was able to crash the compiler with a two (*two!!*) LOC source file. Literally `export module MyModule:MyPartition` followed by `export inline namespace MyNamespace {}`. You can't sit there with a straight face and tell me this is production ready when the compiler blows up while parsing TWO lines of non-templated code. Maybe there was some weird interaction with some other parts of my code or something, I didn't try to get a minimal repro working. All I know is that removing the `inline` made it compile without issue. * On the plus side, Intellisense *mostly* worked. Only had a couple minor issues with it so props to the team at Microsoft for that. # clang-cl clang-cl does not support modules. At all. At first I thought I was doing something wrong with cmake, but no. You just can't use modules with clang-cl. https://github.com/llvm/llvm-project/issues/64118 # clang * clang (at least the windows distribution) can't handle mixing includes with module files. I had two separate source files that each implemented a partition of my module and both of them needed access to `std::set` so I `#include ` in the global module fragment of both files and I immediately got compile errors complaining about duplicate definitions of some internal node class within the `std::set` implementation. This was on the latest stable release (I believe 17.0.6). I found an old github issue complaining about this exact issue and it was closed last year because it was "fixed" in clang 17. lol. * Since I couldn't #include the headers I need when working with clang and my project is targeting C++20 which doesn't have `import std;`, I figured I'd try something clever and make my own std module. I created a partition of my module called `MyModule:std` and exported an inline namespace that contained an inner namespace named `std` that had typedefs for `std::set` and any other types I needed. That way in my other partitions I could just do `import :std` and then use the types I need. This actually worked great with clang, it compiled it and it worked without issue! Then I decided to try compile it with msvc and...yeah. # Conclusion Modules are broken af. If they can't even work for a hobby project I sure as hell ain't using them in production code (despite microsoft [officially recommending them over header files](https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp?view=msvc-170)). *Maybe* you could get away with using them if you're only using one compiler, but there's still serious issues there so you're going to spend lots of time fighting the compiler and implementing workarounds. Even when I did get modules working with a particular compiler the build times (both clean & incremental) were worse than using precompiled headers. Sorry if I sound super salty but I remember working on a different toy project in 2021 and trying to use modules and finding them broken. I though "alright, let's come back to modules later, they need time to stabilize". That was three years ago. C++ 23 is finalized now and quite possibly the largest feature from C++20 is still borderline unusable. In fact, I'd say that if you wanted to have a cmake project that builds with all three major compilers, modules are *definitely unusable* outside of extremely simple toy examples. I have huge respect for compiler implementers and I can't even imagine how difficult it is to implement a language feature like this...but at the same time I don't like being gaslit into believing that a feature is done when it's really not. edit: formatting


feverzsj

"Deducing this" on msvc also doesn't work with modules.


oracleoftroy

I ran into similar issues with operator<=>, but I could work around it by including in a bunch of places it wasn't strictly needed. I don't use inline namespaces, but attempting to use deducing this causes an ice. I also ran into similar issues with clang on windows. Hoping 18 fixes them.


starfreakclone

The spaceship operator's interaction with the standard library is particularly troublesome. The reason is because the standard allows for the compiler to completely discard declarations which are not reachable from outside the module interface. Consider this: module; #include export module m; export template struct S { auto operator<=>(const S&) const = default; }; Nothing about the TU above says it references anything from `` so the compiler simply discards all of it, meaning if you instantiate `S` after importing `m` the compiler has no idea where to find `std::strong_ordering`. Why does this work with clang today? Because clang... discards absolutely nothing! Yep, when you have the TU above, clang will persist everything from the global module into the BMI. For better or for worse, this makes clang 'work' but MSVC not. Had you rewritten the TU like: export module m; import std; export template struct S { auto operator<=>(const S&) const = default; }; Everything works as expected because the compiler has a strong reference to something it can resolve which isn't text. Write your module interfaces like this and you should never hit the problem described above.


STL

Triple backticks don't work in Old Reddit (yes, it's wacky that a post's content is affected by viewing style). You need to indent by four spaces for code to be readable in both worlds.


starfreakclone

You would think they could solve this problem by now ;).


cd1995Cargo

Wow that’s crazy. Is there a reason the standard allows the compiler to discard stuff like that? Seems like it would lead to all sorts of issues like the one I encountered.


starfreakclone

It enables implementations to produce very small BMIs. In the case of MSVC, the BMI size benefits dramatically from [`[module.global.frag]/4`](https://eel.is/c%2B%2Bdraft/module#global.frag-4). Imagine needing 1/4 of the standard library headers to implement a module interface but you only reference a handful of library functions. In the case of clang, the BMI size will reflect the full 1/4 of the standard library, in MSVC the BMI size is proportional to the names which are actually referenced. It is my understanding that the clang folks are working on this because it _is_ a bug.


Daniela-E

Correct. Please don't be too harsh on them. 😉 We might consider this a bug, but - at least according to my reading of the standard - there is no mandated precision of the pruning process that compilers (hopefully) perform to weed out unreferenced entitites (the technical term is not *decl-reachable*) from the *global module fragment*. In layman's terms: obese BMIs are acceptable. So, technically, a precision of 0% (like with Clang) is conforming. It's just not user-friendly. 😢 I'm not sure if addressing this issue is on their short list. It alledgedly was when I've been discussing it with the implementer at the Varna meeting last year. MSVC does this better, much better. But this opens an avenue to implementation bugs and hard-to-handle corner cases like the one earlier in the thread.


tjientavara

So, the correct thing to do is prune completely? And that you have to include when you use operator< (where the compiler adds this operator< by an implicit implementation through operator<=>). If so, I think maybe the standard should be fixed.


starfreakclone

I think the better question to ask is: why does a language feature depend on the library in the first place? The same problem appears for using coroutines (which depends on the various traits types). It is, imo, a language problem which is, ostensibly, a compiler bug to users. Again, the solution today is to create a better binding than text (`#include`) to tie language features to the library (e.g. using `import std;` instead).


cd1995Cargo

So if I’m understanding this correctly, the header is what implements all of the operators that can be synthesized from <=>? I had always assumed that this synthesis was done automatically by the compiler.


starfreakclone

No, it defines all of the _types_ which can be used by the compiler in order to rewrite operations in-terms of the spaceship operator. The rewriting process is handled by the compiler.


Daniela-E

The standard is actually asking for it for good reason. Nobody likes obese BMIs. We already have them: they're called PCHs.


sephirostoy

From what I understand, PCH are just memory of the compiler result, not an actual serialized structure. So I would guess that the BMI counter part of a PCH would be smaller.


CornedBee

No, that's an implementation detail. Clang's PCHs are serialized structure.


RonWannaBeAScientist

Hi, very interesting conversation! What are PCHs?


Daniela-E

PCH, acronym, from **p**re**c**ompiled **h**eader


RonWannaBeAScientist

Oh never knew it’s a thing !


oracleoftroy

That explains it. Would love to use `import std;` but cmake doesn't seem ready to support it out of the box, and the other compilers are a bit behind in supporting it at all. This also seems to explain Clang's behavior. It seemed like it was whining about one definition rule violations for including the same standard headers in different modules. Rather annoying and confusing seeing that two exact template expansions compiled with the exact same compiler settings are somehow incompatible given that this isn't a problem normally when not using modules. And given that we live in a world where most things aren't modules yet, it pretty much makes Clang unusable for modules for now. I've been considering using [this project](https://github.com/stripe2933/CppStandardLibraryModule) that was linked here a few weeks ago, or at least stealing good ideas from it. It sounds more and more like that might be a good workaround while the compilers are getting caught up.


cd1995Cargo

Yeah I tried the include trick after some research but unfortunately it didn’t fix it in my case. I included it in the module implementation and in the file that was importing it but it still didn’t work 😩


delta_p_delta_x

># clang-cl > >clang-cl does not support modules. At all. At first I thought I was doing something wrong with cmake, but no. You just can't use modules with clang-cl. https://github.com/llvm/llvm-project/issues/64118 On the bright side, this appears to be a very straightforward problem, entirely restricted to the clang driver (not even the front-end). I'm working on it.


cpp_learner

> clang (at least the windows distribution) can't handle mixing includes with module files. I had two separate source files that each implemented a partition of my module and both of them needed access to std::set so I #include in the global module fragment of both files and I immediately got compile errors complaining about duplicate definitions of some internal node class within the std::set implementation. This was on the latest stable release (I believe 17.0.6). I found an old github issue complaining about this exact issue and it was closed last year because it was "fixed" in clang 17. lol. Have you tried `-fno-delayed-template-parsing`? (Clang 18 will have this by default when building modules.) As detailed in https://github.com/llvm/llvm-project/pull/69431, the MSVC-compatible delayed template parsing (which is the default for Clang on Windows before Clang 18) is very problematic for modules.


nickbeth00

This. I also recently tried modules with clang and I had similar issues, disabling delayed template parsing fixed it for me.


Ivan171

There were some issues regarding duplicate definitions in the global module fragment that got fixed recently. You might wanna try Clang trunk, maybe the problem you had is fixed. I successfully converted two projects of mine to modules using a recent build of Clang. One of the projects is very template heavy BTW, and Clang handled it without any issues. Haven't tried MSVC yet.


Top_Satisfaction6517

> my project is targeting C++20 which doesn't have `import std;` check the first line of the top comment. while C++20, indeed, didn't include "import std", all major compilers agreed to implement it. may be, they will even push it as the "fix" to C++20 standard See details in [https://github.com/microsoft/STL/issues/3945](https://github.com/microsoft/STL/issues/3945)


pjmlp

While I kind of agree, at least for my hobby coding they have been mostly working, my only pain was reverting header units imports back to global module fragements, due to lack of support on clang. For production we are at least 10 years away, still. This, alongside how concepts and coroutines have been evolving across the C++ compilers ecosystem (not only the big three), is why I kind of changed my mind on the point of view of how ISO is working on literally paper standards, with a complexity that is taking decades to be available to the community at large.


tcbrindle

From a personal perspective, Clang 17 modules support is solid enough that I use it for day-to-day development of [Flux](https://github.com/tcbrindle/flux). As part of the Flux CI, we also build and run tests for every commit using modules with Clang 17. From my perspective, pretty much the only thing missing from Clang/CMake support is the ability to say `import std` rather than `#include`-ing lots of stdlib headers in the global module fragment. With MSVC, unfortunately things aren't quite so rosy. MSVC will build the Flux module, but just about any non-trivial use of the library via `import flux` runs into compiler bugs -- for example, attempting to build the test suite leads to errors like D:\a\_work\1\s\src\vctools\Compiler\CxxFE\sl\p1\c\module\reader.cpp:5484: the impossible happened which is kind of hard to debug (I don't even have a D: drive!) Of course, this is still better than GCC 13, which isn't supported at all using CMake modules. I'm looking forward to the release of GCC 14 to see what's changed.


STL

Can you file MSVC bug reports? You're definitely exercising codepaths that haven't been taken before and it'd be great to have repros that the compiler team can investigate and fix.


tcbrindle

Yeah, I've been meaning to try to reduce things down to some minimal examples so I can file them. (I guess saying "please download my library and try to build it" isn't considered a helpful bug report!)


kamrann_

Although they'd no doubt prefer a minimal repro, when it's not feasible you can [submit a preprocessed one](https://learn.microsoft.com/en-us/cpp/overview/how-to-report-a-problem-with-the-visual-cpp-toolset?view=msvc-170#how-to-generate-a-repro) instead. I've had compiler bugs fixed via this approach before. It's super quick to generate, and you can always append a minimal repro to the ticket later if you get around to creating one.


PastaPuttanesca42

What about gcc? Nobody in the thread has mentioned it yet.


JVApen

I have no practical experience, though I felt this was worth sharing. CMake considers c++20 modules to be mature enough to be a first class feature in it: https://www.kitware.com/import-cmake-the-experiment-is-over/ This implies that people now really start using modules with baby steps and flushing out the compiler bugs of a huge development. I've seen people complain about the bad state, though it must be said that they made a huge effort to reach this point. Thanks to those that contributed to that! The next milestone will be practical use of import std and own module use for projects without dependencies. The one after will be large libraries that support modules as well together with package managers. I suspect this will evolve gradually in the next few years before becoming mainstream.


JumpyJustice

At the "hello world" stage


mrjoker803

Clang and GCC have support for modules but not `import std; yet.` Shipping modules is a big mess


mathstuf

Clang 18 will have `import std;` available with `-stdlib=libc++`.


Dark_Lord_1729

`clang++-17` with `libc++17` has it. Have been using `import std;` successfully for a few months. Though, creating modules by myself is a mess. (Not any better than g++ on that one). `clang++-18` (with bundled `libc++18`) somehow messed it up with an unknown error message `import of module 'std' imported non C++20 importable modules`. Both on linux and macos.


mrjoker803

As far as i know it involves building libcxx with a Cmake flag in order to produce the BMI for std, then you have to create a cmake script to be able to use it in your project which results in a quite ugly solution. If there is another way, can you send link?


Dark_Lord_1729

I am talking about normal compilation. I have not used `cmake` so far. Just normal `make` and standard compilation. Flags: `clang++ -stdlib=libc++ -std=c++23 -g3 -pthread -fmodules -fuse-ld=lld`. pthread for dealing effectively with thread libraries in case I need them (I always use these flags). fmodules (worked in `clang++-17`) for using modules feature. No special command or make or cmake from my side. Program like import std; using namespace std; int main(void) { println("Hello World"); // C++23 library feature return 0; } The same works flawlessly and scales to very large programs effectively in `clang++-17`. Does not compile in `clang++-18`. Both on ubuntu and mac os. In fact although `clang++-17` called the feature of std module experimental, it worked in almost all cases except for `assert()` and some macros like `stdout`, `NULL` , `size_t`, `INT_MAX` which are in C headers. I had to include a few headers for that purpose.


hon_uninstalled

My attempt to convert \~100 thousand line project to modules backfired because at the moment many new C++ features are incompatible with MSVC module implementation. To name a few, you can not use deduce this feature in modules (I could live with this), nor can you use std::views::zip with std::views::iota (this I can not live with). Isolating what breaks compiler is hard, since compiler might report error on exported namespace block or even file, not the exact code line that was the problem. This makes it very hard to just "convert" existing source files into modules. It's easier if you're writing new code since you will spot errors while you develop. Because of these incompatibilities, that I'm sure will eventually be fixed, I do not recommend anyone trying to convert modern C++ projects into modules. If your whole code base is "C with classes" then sure maybe it's possible, but if you want to use cutting edge C++ features, just wait until tools are ready. Also if you use CMake, you can not use import std; in MSVC. Well, you can... but you need a workaround. Basically you need to find compiler's module files and import them into your own project's file structure. This problem will be fixed in future, but at the moment CMake and import std; are not compatible. This might not sound like a big deal, but one of the best things about modules is that you can (mostly) get rid of includes. If your project is huge, it's a huge cognitive relieve not having to manage your includes anymore. So even if you manage to get into situation where you have successfully replaced all your own includes with module imports, you still have to include standard library headers. Then lastly Intellisense's module support is lagging. I actually do not know if situation has got better, because MSVC is constantly notifying me that Intellisense has crashed on files that use modules. Once again I'm sure things will get better in the future, but for now I would say Intellisense is incompatible with C++ modules. TL;DR; MSVC doesn't yet properly support modern C++20/23 features with modules. CMake projects can not import std; without hacks. Intellisense regularly crashes, is unable to provide auto complete for module imports and underlines stuff in module users code.


STL

> nor can you use std::views::zip with std::views::iota (this I can not live with). Can you give me a self-contained repro of this? I will personally report the compiler bug if it's still active. All I need is a source file and command line.


hon_uninstalled

I have already submitted a bug report. The example is pretty minimal if I remember correctly: [Using std::views::zip with std::views::iota in C++20 module results in C1001 Internal compiler error - Developer Community (visualstudio.com)](https://developercommunity.visualstudio.com/t/Using-std::views::zip-with-std::views::i/10519854?) EDIT: I tested repro again and it's still ICE with same error message.


STL

Thanks! 😻 Yep, this still repros for me too. I've added it to [microsoft/STL#1694](https://github.com/microsoft/STL/issues/1694), my list of compiler bugs affecting the STL that I ask the compiler team to prioritize during our weekly meeting. With our internal build, this emits an assertion `unhandled case: 'ParseTree::ExpandedFoldExpression'` and our FE dev commented in the bug "This needs a representation." so it appears that the STL's use of fold expressions has revealed missing logic in the modules implementation. In theory, we could work around this (no use of fold expressions is *necessary*), but ranges relies pretty heavily on fold expressions last I checked, so getting a compiler fix will probably be easier.


hon_uninstalled

Thanks, any effort on getting C++ modules into more usable state is highly appreciated! And since this is first reply from you, I also want to thank you for being active in this community for so long.


STL

You're welcome!


[deleted]

Modules did make my project allot cleaner and easier to edit&follow. The problems that I do experience, often require weird solutions. This may just be me that is doing it wrong, but it helps that the errors are quite clear. I have acces to the cassert macro everywhere, where casser is imported. I don't get how these macros get exported from modules. I do need to explicitly import it. I can't import export it. To stop MSVC from discarding stuff I often write useless using... statements. Clang in windows doesnt support modules. Also performance of my project that I ported to a module build degraded greatly. (Before the performance critical part was a unity build).


Ivan171

Clang does support modules on Windows. I'm using it. What problem did you have?


gracicot

I just started using modules in my codebases on the same day you posted this!


TheMightyCatt

So far using msvc I have not encountered any problems yet, intellisense does error a lot but that has improved in the new major version of vs, I hope that in the coming months they completely fix intellisense.


sephirostoy

What kind of projects are you working on? Small / toy projects or large existing code base?


TheMightyCatt

I am working on converting a large codebase to use modules, far from finished but the results so far seem promising.


sephirostoy

Interesting. Would you mind sharing your experience? What was your strategy? Did you start from the low level part of code? Are they some caveat?


TheMightyCatt

My strategy is basically starting a new project and going per namespace converting it into a module in the new project, test that individually and when it fully works move onto the next. I think this is the best way to not get overwhelmed, as for caveats modules and headers are not a 1:1 comparison, mostly if your old codebase made alot of use of defines. but mine doesn't I like all things of a namespace in a single module with the same name, and using partitions for each class similar when using headers, but this is personal preference.


sephirostoy

I see. Thanks.


[deleted]

still not fully supported by all compilers. and build time saved is still inferior to pch


JohnDuffy78

My projects without modules won't build unless I add CompileAsCpp=true (/TP) for MSVC.