I agree that article is thin on technical details, but it does provide arguments against the textual-inclusion technique that C++ (and C) currently use.
However, that points to a Clang implementation of modules for Objective C. And the proposed solution it points to is eight years old. For more details, see the most recent proposal: http://isocpp.org/files/papers/n4214.pdf
The semantics are the problem, as they require re-parsing every header transitively every time, and this defines new syntax with new semantics.
Large C++ projects end up with compile time tending towards O(n^2) in the number of files in the project; this will save tens of minutes to hours on every project build.
Precompiled headers were supposed to help this, but don't work well in practice, since they become hundreds of MB in size, which is just as slow as #includes, so on large projects that I've worked on we took the inverse approach; concatenating all the source code for each linkage unit.
Say you're building a library comprised of files a.cpp, b.cpp, c.cpp, ..., z.cpp, many of which share various #includes.
Generate an intermediate file that contains the following.
I realize it's an ugly hack, and doesn't play well with using global variables (though you shouldnt do this anyway!), and you have to be very careful with include guards, but if you make these simple accommodations, you can get large C++ projects to compile significantly faster, at the cost of huge RAM usage for each "everything.cpp" that you compile. A nice side effect is that the optimizer has more context to work with, so you sometimes end up with smaller or faster executables.
You don't usually improve the standard for legacy code. You want backward compatibility, sure, but the expectation that a new standard automatically makes old code not suck is just setting you up to be disappointed.
What C++ has allowed us to do is slowly (sometimes wholesale), add the new stuff to old code or just write new code that doesn't suck as much.
I have always thought that C++ took the wrong route here.
Backward compatibility can be solved via a compiler flag too.
So the language can evolve, and deprecate older sub-awesome solutions, while allowing people to still use that via a "--my-code-still-uses-feature-x-and-i-dont-want-to-update" compiler flag.
You could have deprecated :
- #includes and have a decent mechanism
- std::pair when you introduce std::tuple
- perhaps new when you have make_shared and make_unique
- etc etc.
There's also a gentle push towards the more recent solutions as at one point compiler vendors will not maintain these flags forever because it's no longer part of the language.
The presence of a language feature is already signalled via the __cplusplus define, so it is already done that way.
I think C++ is very pragmatic in the way it has been done so far, but I am not looking forward to the new __* keywords for resumable functions. I think it's fair to steal the "await" and "yield" keywords back from programmers so my eyes don't bleed. I've already been conditioned to treat __whatever as a platform-specific thing to avoid in my code.
14 comments
[ 3.0 ms ] story [ 40.7 ms ] threadHowever, that points to a Clang implementation of modules for Objective C. And the proposed solution it points to is eight years old. For more details, see the most recent proposal: http://isocpp.org/files/papers/n4214.pdf
It was discussed on HN about a month ago: https://news.ycombinator.com/item?id=8452886
Large C++ projects end up with compile time tending towards O(n^2) in the number of files in the project; this will save tens of minutes to hours on every project build.
Say you're building a library comprised of files a.cpp, b.cpp, c.cpp, ..., z.cpp, many of which share various #includes.
Generate an intermediate file that contains the following.
#include "a.cpp" #include "b.cpp" ... #include "z.cpp"
And compile that instead.
I realize it's an ugly hack, and doesn't play well with using global variables (though you shouldnt do this anyway!), and you have to be very careful with include guards, but if you make these simple accommodations, you can get large C++ projects to compile significantly faster, at the cost of huge RAM usage for each "everything.cpp" that you compile. A nice side effect is that the optimizer has more context to work with, so you sometimes end up with smaller or faster executables.
What C++ has allowed us to do is slowly (sometimes wholesale), add the new stuff to old code or just write new code that doesn't suck as much.
You could have deprecated :
- #includes and have a decent mechanism
- std::pair when you introduce std::tuple
- perhaps new when you have make_shared and make_unique
- etc etc.
There's also a gentle push towards the more recent solutions as at one point compiler vendors will not maintain these flags forever because it's no longer part of the language.
I think C++ is very pragmatic in the way it has been done so far, but I am not looking forward to the new __* keywords for resumable functions. I think it's fair to steal the "await" and "yield" keywords back from programmers so my eyes don't bleed. I've already been conditioned to treat __whatever as a platform-specific thing to avoid in my code.