The problem with C++ modules is that they are empirically inferior to headers and separate compilation units. The pre processor and linker, as derided as they are, allow for scaling of software size to extremes not possible with supposedly superior languages’ supposedly superior module systems. Want to build a >billion line of code OS? You can do that with headers and separate compilation units. Good luck doing that…
The Linux kernel is tens of millions of lines, so I'm rather doubtful at the existence of this OS over a billion lines.
What to do with C++ modules?
201–210 of 269 posts
Re: What to do with C++ modules?
#202Earlier quoted context omitted.
C++ can never change the way move vs copy semantics work, which is precisely the opposite of Rust’s. It’s the basis for rust’s ownership model, and it’s no small difference. Without this I don’t see how C++ can ever get a workable ownership model like Rust’s.
C++ just gives you the option to have it both ways. You are free to design your library in a way that your users only see one of these.
C++ didn't get that. The proposal paper at the time says it's impossible (for C++). But what they did propose was the feature you've seen in C++ today, which they call "move", but it has slightly odd (though convenient to implement, Worse Is Better after all) behaviour.
Now you can make this C++ "move" behaviour out of destructive move, that behaviour is roughly what Rust calls std::mem::take and it's sometimes useful, which is why that function is provided. But, often it's not really what you wanted, and if you actually wanted destructive move but only have this C++ imposter then you need to perform the entire take, then throw away the newly created object. You will find lots of C++ code doing exactly that.
So, no, you can't "design your library" to deliver the desirable property in C++. It's just another of the dozens of nagging pains because of design mistakes C++ won't fix.
Re: What to do with C++ modules?
#203All that the C++ committee needed to do was just introduce "import" as "this is the same as include except no context can leak into it". Would have been dirt simple to migrate existing codebases over to using it (find and replace include with import, mostly), and initial implementations of it on the compiler side could have been nearly identical to what's already there, while offering some easy space for optimizing i…
What do you mean by "no context can leak into it"? Do you mean it shouldn't export transitive imports? As in `#include ` also performs `#include ` but `import vector` would only import vector, requiring you to `import iterator`, if you wanted to assign `vec.begin()` to a variable? Or is it more like it shouldn't matter in which order you do an import and that preprocessor directives in an importing file shouldn't aff…
Re: What to do with C++ modules?
#204The problem with C++ modules is that they are empirically inferior to headers and separate compilation units. The pre processor and linker, as derided as they are, allow for scaling of software size to extremes not possible with supposedly superior languages’ supposedly superior module systems. Want to build a >billion line of code OS? You can do that with headers and separate compilation units. Good luck doing that…
I don't see anything that makes this impossible. In fact I think this is just a result of nobody making a project of that scale in those languages yet, rather than it being fundamentally impossible.
It's a fact that:
- Super large software tends to be C or C++
- One of the unique features of C and C++ is the way software is organized (headers and separate compilation).
- Attempts to bring other languages' approach to modules to C++ have been a complete disaster.
Hence it's an empirical fact that C and C++ have a superior approach to software scaling, and that approach is headers and separate comp. And a preprocessor with macros.
Re: What to do with C++ modules?
#205Earlier quoted context omitted.
This is true ... except that Rust doesn't actually do any better in that regard. Rust solves 1 category of problems in a way that is not without its costs and other consequences. That is it. There are projects where this is very important, there are other projects where its virtually useless and the consequences just get in the way. It is not magic. It doesn't make anything actually 'safe'.
sure, but don't forget that rust gives us also a nice tooling, functional syntax sugar like pattern matching, enums, monads; and other more or less useful things like explicit lifetimes
Re: What to do with C++ modules?
#206Earlier quoted context omitted.
The goal is to be able to import that 20yo battle-tested library into your C++20 codebase and it just works .
there are really a lot of simpler solutions than switching the standard of the whole codebase. E.g. write wrapper which interface doesn't require a new standard.
Re: What to do with C++ modules?
#207Earlier quoted context omitted.
Including or importing a templated class/function should not require bringing in the definition. That's why #includes and imports are so expensive, as we have to parse the entire definition to determine if template instantiations will work. For normal functions or classes, we have forward declarations. Something similar needs to exist for templates.
And it doesn't in D. We call such modules ".di files", which consist only of declarations. D does not require names in global scope to be declared lexically before they are used. C++ only does this for class/struct scopes. For example: int bar() { foo(); } int foo() { bar(); } compiles and runs (and runs, and runs, and runs!!!).
But how do you handle a template substitution failure? In C++:
template
auto bar(T x, T y)
{ return x + y;}
The compiler has no idea whether bar(1, 2); will compile unless it parses the full definition. I don't understand how the compiler can avoid parsing the full definition.The expensive bit in my experience isn't parsing the declaration, it's parsing the definition. Typically redundantly over thousands of source files for identical types.
Re: What to do with C++ modules?
#208Earlier quoted context omitted.
You have it backwards. Everyone wants a new standard but no one wants to fix the code to make it work with a new way. They would rather introduce a whole new thing. We want new stuff, but in order to do that we must break old stuff. Like breaking old habits, except this one will never die.
we spent a billion dollars to rewrite our code breaking everything. 15 years latter and we have a better product than the old stuff- but 15 years ago was pre c++11, and rust didn't exist. i cannot honestly ask for another billion dollars to repeat that again and we are stuck. We must keep the old code running and if your new thing isn't compatible with whatever we did back then you are off the table. c++26 still buil…
I empathize. This is where rust could really help but there’s a lot of hate around “new” so it sits. The C++2042 standard will still have to be able to solve for C++98. The language will die. A pointer is a pointer and it shouldn’t need weak_ptr, shared_ptr, unique_ptr etc. If you expose it, it’s shared. If you don’t, then it could be unique but let the compiler decide. The issue with all these additions is they are opt in for a community that would rather opt out since it means learning/rewriting/refactoring.
I’ve come across this so many times in my career. Thank goodness for AI and LLMs that can quickly decompose these hairball code bases (just don’t ask it to add to it).
I love C/C++ but it’s so old at this point that no sane person should ever start with that.
Re: What to do with C++ modules?
#209Earlier quoted context omitted.
C++ just gives you the option to have it both ways. You are free to design your library in a way that your users only see one of these.
What developers actually wanted, even years back when C++ didn't have anything named "move" was the destructive move semantic. It's an elegant, easy to understand feature for a language. I like it very much in Rust which has it. C++ didn't get that. The proposal paper at the time says it's impossible (for C++). But what they did propose was the feature you've seen in C++ today, which they call "move", but it has slig…
Yes, I understand that there’s a lot of bad code out there and C++ happily enables that. But that was not my point.
Re: What to do with C++ modules?
#210Earlier quoted context omitted.
"if constexpr" introduces a new scope, while "static if" does not. A major divergence, enough to make the features very, very different in terms of what they can actually be used for.
That was a giant mistake on C++'s part, as you cannot do this: static if (feature) { int bar() { betty(); }} ... lots of code ... static if (feature) bar(); Forcing a new scope cuts the utility of it about in half, and there's no way around it. But if you need a scope with D's static if: static if (expression) {{ int x; foo(x); }} the extra { } will do it. But, as it turns out, this is rarely desirable.