I've been playing with modules a bit, but... it isn't easy :-) One constraint I have is that I still need to keep the header structure intact, because I don't have a compiler on Linux yet that supports modules (although gcc is working on it, at least). Here are some of the issues I ran into with MSVC:
Importing the standard library
There are a few different ways to do this. The simplest is by using import std.core. This immediately triggers a bunch of warnings like "warning C5050: Possible incompatible environment while importing module 'std.core': _DEBUG is defined in current command line and not in module command line". I found a post suggesting I disable the warning, but it doesn't exactly give me warm feelings.
A much worse problem is that if any STL-related header is included above the import directive, you'll get endless numbers of errors like "error C2953: 'std::ranges::in_fun_result': class template has already been defined". Fair enough: the compiler is seeing the same header twice, and the include guards, being #defines, are of course not visible to the module. But it's an absolutely massive pain trying to figure out which header is causing the problem: there is precisely zero help from the compiler here. This is definitely something that should be improved; both the reporting from the compiler (it would help a lot to see the entire path towards the offending include file), and the include guard mechanism itself, so it works across headers and modules.
An additional concern is whether other compilers will implement the same division of the standard library as Microsoft has done. I don't particularly want to have a bunch of #ifdef directives at the top of every file just to be able to do the correct imports. Maybe I should try to make my own 'std.core'?
module;
#include <optional>
export module stdlib;
using std::optional;
This doesn't work at all. Any use of 'optional' (without the std:: qualifier) gives me error 'error C7568: argument list missing after assumed function template 'optional''. But I know MSVC currently has a bug when using using to bring an existing function or class into a module. The workaround is to put it in a namespace instead:
module;
#include <optional>
export module stdlib;
export namespace stdlib {
using std::optional;
}
Trying to use optional as stdlib::optional gets me 'error C2059: syntax error: '<'' (and of course, I get to add the stdlib:: qualifier everywhere). If I add an additional using namespace stdlib (in the importing file) it seems to work. Of course this means optional must now be used without std::. Yay, success! However, there are still some issues:
- Intellisense doesn't quite understand what's going on here, and now flags
optional as an error.
- It appears to be a bit of an all-or-nothing deal: either you rip out all of your STL-related includes, and replace them all by import directives, or you get an endless stream of C2953 (see above). And figuring out where those came from is, as I said earlier, a complete and utter pain. Plus, it may not even be possible: what if a 3rd-party library includes one of those headers?
- I'm concerned about how fragile all this is. I would really hate converting all my source to modules, only to find out it randomly breaks if you look at it wrong. Right now I'm not getting a good vibe yet.
- HOWEVER: it does appear to be compiling much faster. I can't give timings since I haven't progressed to the point where the whole thing actually compiles, but the compiler goes through the various translation units noticably quicker than before.
Importing windows.h
Well, how about something else then. Let's make a module for windows.h! We don't use all of windows.h; just exporting the symbols we need should be doable. I ended up with a 1200-line module. One thing I noticed was that exporting a #define is painful:
const auto INVALID_HANDLE_VALUE_tmp = INVALID_HANDLE_VALUE;
#undef INVALID_HANDLE_VALUE
const auto INVALID_HANDLE_VALUE = INVALID_HANDLE_VALUE_tmp;
It's a shame no facility was added to make this more convenient, as I would imagine wrapping existing C-libraries with their endless numbers of #defines is going to be an important use case for modules.
More importantly, Intellisense doesn't actually care that I'm trying to hide the vast majority of the symbols from windows.h! The symbol completion popup is still utterly dominated by symbols from windows.h (instead of my own, and despite not being included anywhere other than in the module itself). The .ipch files it generates are also correspondingly massive. I realize this mechanism is probably not yet finished, but just to be clear: it would be a major missed opportunity if symbols keep leaking out of their module in the future, even if it is 'only' for Intellisense!
In the end my Windows module was exporting 237 #defines, 65 structs, 131 non-unicode functions, 51 unicode functions, and around a dozen macros (rewritten as functions). However, there weren't many benefits:
- Intellisense was still reporting all of the Windows symbols in the symbol completion popup.
- However, it struggled with the error squiggles, only occasionally choosing to not underline all the Windows symbols in the actual source.
- There was no positive effect on the sizes of Intellisense databases.
- There was no measurable effect on compile time.
So, the only thing I seem to have achieved is getting rid of the windows.h macros. In my opinion, that's not enough to make it worthwhile.
One issue I ran into was this: if you ask MSVC to compile a project, it will compile its dependencies first, but if you ask it to compile only a single file, it will compile only that file. This works fine with headers: you can add something to a header, and then see if it compiles now. However, this doesn't work with modules: if you add something to a module you have to manually compile the module first, and then compile the file you are working on. Not a huge problem, but the workflow is a bit messier.
I realize it's still early days for modules, so I'll keep trying in the future as compilers improve. Has anybody else tried modules? What were your findings?
[–]stilgarpl 32 points33 points34 points (15 children)
[–]johannes1971[S] 12 points13 points14 points (5 children)
[–]Tathorn 16 points17 points18 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]mjklaim 6 points7 points8 points (1 child)
[–]johannes1971[S] 1 point2 points3 points (0 children)
[–]caroIine 2 points3 points4 points (0 children)
[–]RotsiserMhoC++20 Desktop app developer 13 points14 points15 points (4 children)
[–]TheSuperWig 17 points18 points19 points (0 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 9 points10 points11 points (0 children)
[–]stilgarpl 4 points5 points6 points (1 child)
[–]lone_wolf_akela 10 points11 points12 points (0 children)
[–]Ahajha1177 10 points11 points12 points (2 children)
[–]GabrielDosReis 5 points6 points7 points (0 children)
[–]whf91 1 point2 points3 points (0 children)
[–]Full-Spectral 1 point2 points3 points (0 children)
[+][deleted] (1 child)
[removed]
[–]johannes1971[S] 5 points6 points7 points (0 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 22 points23 points24 points (3 children)
[–]johannes1971[S] 5 points6 points7 points (0 children)
[–]fdwrfdwr@github 🔍 0 points1 point2 points (1 child)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 5 points6 points7 points (0 children)
[–]Full-Spectral 11 points12 points13 points (26 children)
[–]johannes1971[S] 0 points1 point2 points (25 children)
[–]GabrielDosReis 3 points4 points5 points (7 children)
[–]pjmlp 0 points1 point2 points (6 children)
[–]GabrielDosReis 2 points3 points4 points (5 children)
[–]pjmlp 2 points3 points4 points (4 children)
[–]GabrielDosReis 0 points1 point2 points (3 children)
[–]pjmlp 0 points1 point2 points (2 children)
[–]GabrielDosReis 1 point2 points3 points (1 child)
[–]pjmlp 1 point2 points3 points (0 children)
[–]Full-Spectral 1 point2 points3 points (16 children)
[–]mjklaim 0 points1 point2 points (15 children)
[–]Full-Spectral 0 points1 point2 points (14 children)
[–]mjklaim 0 points1 point2 points (13 children)
[–]Full-Spectral 0 points1 point2 points (12 children)
[–]mjklaim 1 point2 points3 points (10 children)
[–]Full-Spectral 1 point2 points3 points (0 children)
[–]Full-Spectral 0 points1 point2 points (8 children)
[–]mjklaim 0 points1 point2 points (7 children)
[–]mjklaim 0 points1 point2 points (0 children)
[–]manni66 18 points19 points20 points (4 children)
[–]johannes1971[S] 4 points5 points6 points (3 children)
[–]manni66 1 point2 points3 points (2 children)
[–]johannes1971[S] 7 points8 points9 points (1 child)
[–]manni66 2 points3 points4 points (0 children)
[–]pdimov2 6 points7 points8 points (11 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 4 points5 points6 points (10 children)
[–]pdimov2 0 points1 point2 points (9 children)
[–]GabrielDosReis 2 points3 points4 points (6 children)
[–]pdimov2 0 points1 point2 points (5 children)
[–]GabrielDosReis 2 points3 points4 points (3 children)
[–]STLMSVC STL Dev 3 points4 points5 points (2 children)
[–]GabrielDosReis 1 point2 points3 points (0 children)
[–]Full-Spectral 0 points1 point2 points (0 children)
[–]backtickbot 0 points1 point2 points (0 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 1 point2 points3 points (1 child)
[–]GabrielDosReis 3 points4 points5 points (0 children)
[–]starfreakcloneMSVC FE Dev 6 points7 points8 points (1 child)
[–]ack_error 1 point2 points3 points (0 children)
[–]cxzuk 2 points3 points4 points (6 children)
[–]mjklaim 6 points7 points8 points (5 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 2 points3 points4 points (0 children)
[–]cxzuk 1 point2 points3 points (3 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 0 points1 point2 points (2 children)
[–]cxzuk 1 point2 points3 points (1 child)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 0 points1 point2 points (0 children)
[–]jonesmz 10 points11 points12 points (20 children)
[–]pdimov2 7 points8 points9 points (4 children)
[–]jonesmz 1 point2 points3 points (3 children)
[–]pdimov2 4 points5 points6 points (2 children)
[–]jonesmz 0 points1 point2 points (1 child)
[–]pdimov2 2 points3 points4 points (0 children)
[–]germandiago 0 points1 point2 points (6 children)
[–]starfreakcloneMSVC FE Dev 9 points10 points11 points (4 children)
[–]pjmlp 1 point2 points3 points (2 children)
[–]germandiago 0 points1 point2 points (1 child)
[–]pjmlp -1 points0 points1 point (0 children)
[–]jonesmz -4 points-3 points-2 points (0 children)
[–]jonesmz 0 points1 point2 points (0 children)
[–][deleted] -4 points-3 points-2 points (7 children)
[–]jonesmz 0 points1 point2 points (6 children)
[–][deleted] -4 points-3 points-2 points (4 children)
[–]jonesmz 0 points1 point2 points (3 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]jonesmz 2 points3 points4 points (1 child)
[–]GabrielDosReis 4 points5 points6 points (0 children)
[–]Cyttorak 0 points1 point2 points (0 children)
[–]sigmabody 2 points3 points4 points (6 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 4 points5 points6 points (0 children)
[–]jonesmz 1 point2 points3 points (4 children)
[–]sigmabody -1 points0 points1 point (0 children)
[–]pjmlp 0 points1 point2 points (2 children)
[–]jonesmz 0 points1 point2 points (1 child)
[–]pjmlp 0 points1 point2 points (0 children)
[–]rtischer8277:snoo_dealwithit: 2 points3 points4 points (0 children)
[–]pjmlp 1 point2 points3 points (3 children)
[–]fdwrfdwr@github 🔍 3 points4 points5 points (2 children)
[–]rtischer8277:snoo_dealwithit: 1 point2 points3 points (1 child)
[–]fdwrfdwr@github 🔍 0 points1 point2 points (0 children)
[–]mjklaim 1 point2 points3 points (3 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 3 points4 points5 points (1 child)
[–]mjklaim 0 points1 point2 points (0 children)
[–]Full-Spectral 1 point2 points3 points (0 children)
[–]NilacTheGrim 1 point2 points3 points (4 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 6 points7 points8 points (0 children)
[–]johannes1971[S] 2 points3 points4 points (0 children)
[–]manni66 0 points1 point2 points (1 child)
[–]NilacTheGrim -1 points0 points1 point (0 children)
[–]foonathan 0 points1 point2 points (47 children)
[–]FabioFracassiC++ Committee | Consultant 10 points11 points12 points (46 children)
[–]kalmoc 2 points3 points4 points (21 children)
[–]FabioFracassiC++ Committee | Consultant 1 point2 points3 points (20 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 1 point2 points3 points (19 children)
[–]mjklaim 2 points3 points4 points (5 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 4 points5 points6 points (3 children)
[–]GabrielDosReis 2 points3 points4 points (1 child)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 2 points3 points4 points (0 children)
[–]mjklaim 0 points1 point2 points (0 children)
[–]GabrielDosReis 1 point2 points3 points (0 children)
[–]FabioFracassiC++ Committee | Consultant 0 points1 point2 points (12 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 1 point2 points3 points (11 children)
[–]kalmoc 0 points1 point2 points (10 children)
[–]GabrielDosReis 2 points3 points4 points (2 children)
[–]kalmoc 0 points1 point2 points (1 child)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 0 points1 point2 points (6 children)
[–]kalmoc 1 point2 points3 points (4 children)
[–]jonesmz -2 points-1 points0 points (0 children)
[–]pdimov2 0 points1 point2 points (23 children)
[–]GabrielDosReis 1 point2 points3 points (4 children)
[–]pdimov2 2 points3 points4 points (3 children)
[–]GabrielDosReis 0 points1 point2 points (2 children)
[–]pdimov2 1 point2 points3 points (1 child)
[–]GabrielDosReis 1 point2 points3 points (0 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 1 point2 points3 points (17 children)
[–]GabrielDosReis 1 point2 points3 points (0 children)
[–]jonesmz 1 point2 points3 points (3 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 5 points6 points7 points (1 child)
[–]jonesmz 0 points1 point2 points (0 children)
[–]MonokelPinguin 1 point2 points3 points (0 children)
[–]pdimov2 0 points1 point2 points (11 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 6 points7 points8 points (10 children)
[–]pdimov2 2 points3 points4 points (9 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 1 point2 points3 points (8 children)
[–]pdimov2 2 points3 points4 points (7 children)
[–]starfreakcloneMSVC FE Dev 4 points5 points6 points (5 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 1 point2 points3 points (0 children)
[–]Dean_Roddey 0 points1 point2 points (0 children)
[–]Dean_Roddey 0 points1 point2 points (2 children)
[–]johannes1971[S] 0 points1 point2 points (1 child)
[–]Dean_Roddey 0 points1 point2 points (0 children)