Live data from Hacker News

What to do with C++ modules?

nibblestew.blogspot.com

201–210 of 269 posts

Re: What to do with C++ modules?

#201

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.

That's just the kernel. An OS is more than the kernel

Re: What to do with C++ modules?

#202
post #187

Earlier 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.

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 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?

#203

All 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…

[deleted]

Re: What to do with C++ modules?

#204

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…

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 doesn't matter if you or I see what makes it 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?

#205
post #29

Earlier 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

[dead]

Re: What to do with C++ modules?

#206
post #135

Earlier 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.

Mmm pimpl’s and acne…

Re: What to do with C++ modules?

#207
post #67

Earlier 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!!!).

> D does not require names in global scope to be declared lexically before they are used. C++ only does this for class/struct scopes.

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?

#208

Earlier 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…

This. This is why C++ is stuck. The effort required to rewrite old shit code (that works, does its job, makes money) is just too valuable to the company so it sits. All vendors must conform or else be shown the door. No innovation can take place so long as Clu has its claws in our company.

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?

#209
post #187

Earlier 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…

I am still confused about what you are claiming to be not possible in C++ when you are designing your library.

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?

#210

Earlier 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.

I would use std::enable_if or C++20 concepts. Both work fine for selectively enabling functions.
Post reply on HN