Live data from Hacker News

What to do with C++ modules?

nibblestew.blogspot.com

251–260 of 269 posts

Re: What to do with C++ modules?

#251
post #141

Earlier quoted context omitted.

> That's the fundamental limitation of modules systems that supposedly prevents this scaling? Not the person you're replying to but I can see a problem with some dependency chains. Let's say you have: stdlib If you only precompile A.hpp (as is commonly done), the many .cpp files can be compiled in parallel once A.hpp is precompiled, and you get a nice speedup. If on the other hand you need to precompile everything, t…

I'm not entirely sure modules systems must face that limitation. C++'s module system, for example, permits separation of module interfaces and module implementations, much like the existing header/implementation system. IIRC OCaml's module system does something similar, though I'm not familiar enough with it to say whether it qualifies as a module system beyond the name. Speaking more abstractly even if there isn't a…

> Speaking more abstractly even if there isn't an explicit interface/implementation separation perhaps compilers could pick out and make available interface information "ahead of time" to alleviate/possibly eliminate the effect of otherwise problematic dependency chains?

I'm not sure how well this would work for non-instantiated templates

> There's also the question of whether super large projects must have problematic dependency chains

Any header precompilation dependency chain is a dependency chain and may end up worse than fully parallel TU compilation if the time to parse said headers is faster than the time to compile them in a serial way.

I can see modules being used, but relegated to, "import std; import fmt; import vulkan (etc)", typically use cases one should already use PCH for.

Re: What to do with C++ modules?

#252
post #247

Earlier quoted context omitted.

> See the other versions I added. I don't think those work either. Not only do neither of those actually end the lifetime of what's passed in, but they have other flaws as well. > template void drop(T &&) {} This literally does nothing. Reference parameters don't affect what's passed in on their own - you need at least something on the other end (e.g., a move constructor) to do anything. For example, consider how thi…

> Not only do neither of those actually end the lifetime of what's passed in >For example, consider how this would be instantiated for std::vector : Great, here you go. https://godbolt.org/z/9v66n6Ta4 And yes, the compiler will not prevent you from using this value. (clang will eventually, I think) But clang static analyzer will happily detect it. https://stackoverflow.com/questions/72532377/g-detect-use-af...

I'm not sure why you keep posting snippets demonstrating C++ rvalue references. We all know what those are, and it's not what we're talking about.

We're talking about how the rust compiler uses move semantics to prevent you from using the moved-from value, such that code like this will not compile:

    let f = Foo::new();
    drop(f);
    f.foo(); // Error: use of moved value
C++'s move semantics do not prevent you from using f after you've moved it. On the contrary, it's intentionally allowed. It's not undefined behavior either, it's "unspecified" behavior, which means "behavior, for a well-formed program construct and correct data, that depends on the implementation". This simply means that it's up to the individual type to decide what happens when a value is moved from. (A string becomes an empty string, for instance, or a vector becomes and empty vector.)

Rust's move semantics mean:

- You don't write a move constructor

- Moves are just memcpy

- The compiler enforces the old value can't be used any more

C++'s move semantics mean:

- You must write a move constructor (rvalue reference constructor)

- Moves are arbitrary code

- The language explicitly allows the moved-from value to continue to be used

That there are certain linter-style tools like clang-tidy which can be configured to warn on using moved-from values is irrelevant: The standard explicitly allows it. It's personal preference whether you should make a habit of using moved-from values in your codebase, which is why this will only ever be a linter thing. The C++ standard would have to completely change its mind and retcon moves to mean something different, if they ever wanted to change this.

Now, the beginning of this thread was someone saying "Rust is basically the wanted fixes to C++ that C++ itself could never adopt for legacy reasons". Then you came back with "I agree with your point except for the 'never' qualifier", implying C++ will eventually support Rust's ideas. But move semantics in C++ are precisely the opposite of those in Rust, because rust-style semantics were deemed impossible to implement in C++, even though it's what people actually wanted at the time. So I think it's fair to say C++ will "never" get Rust-style move semantics.

Re: What to do with C++ modules?

#253
post #43

Earlier quoted context omitted.

I can't think of a C++ project I've worked on that didn't rely on being able to include C headers and have things usually just work. Are there ways of banning C macros from "modular" C++ without breaking that? (Many would find it unacceptable if you had to go through every C dependency and write/generate some sort of wrapper.)

D resolved this problem by creating D versions of the C system headers. Yes, this was tedious, but we do it for each of our supported platforms. But we can't do it for various C libraries. This created a problem for us, as it is indeed tedious for users. We created a repository where people shared their conversions, but it was still inadequate. The solution was to build a C compiler into the D compiler. Now, you can…

> The solution was to build a C compiler into the D compiler.

This is the same solution that Apple chose for Swift Objective C interop. I wonder if someone at Apple was inspired by this decision in D!

Re: What to do with C++ modules?

#254

Back in the 90s, I implemented precompiled headers for my C++ compiler (Symantec C++). They were very much like modules. There were two modes of operation: 1. all the .h files were compiled, and emitted as a binary that could be rolled in all at once 2. each .h file created its own precompiled header. Sounds like modules, right? Anyhow, I learned a lot, mostly that without semantic improvements to C++, while it made…

I've often wondered how the evolution of C and C++ might have been different if a more capable preprocessor (in particular, with more flexible recursive expansion and a better grammar for pattern matching) had caught on. The C++ template engine can be used to work around some of those limits, but always awkwardly, not least due to the way you need Knuth's arrow notation to express the growth in compiler error message volume with template complexity. By the time C++ came out we already had tools like m4 and awk with far more capability than cpp. It's pretty ridiculous that everything else about computing has radically changed since 1970 except the preprocessor and its memory-driven constraints.

Re: What to do with C++ modules?

#255
post #250

Earlier quoted context omitted.

It’s not just for disposing things, it’s also used to decompose things into their constituent parts… like if I had something representing an HTTP response and it contains headers and a body, I could write a `fn into_parts(self) -> (Headers, Body)` that returns the parts you care about while destroying the response object. This is useful in the grpc library I use, which has a response type with some metadata about the…

> compiler will reject programs that use the moved-from value. Yes, this is something the C++ 'language' is not going to specify other than claiming that it is undefined behavior. Doesn't prevent compilers from doing it though, clang will happily do this for you right now in most cases. https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-a...

But it's not undefined behavior. That's the key. It's "unspecified behavior", meaning that according to the standard, it's allowed. A program that reuses a moved-from value is considered valid and well-formed by the standard. It merely delegates how to make this work to the individual implementation (a string becomes an empty string, a vector becomes an empty vector, etc.)

The RFC you posted has nothing to do with move semantics, it's about references outliving what they point to (ie. use-after-free, etc) and similar to Rust's borrow checker.

But here's the thing: move semantics and the borrow checker have nothing to do with each other! The borrow checker ensures that borrowed data (ie. &Foo, equivalent to C++'s references) is sound, it's not the part that enforces move semantics. That happens earlier in the compilation, the compiler enforces moves well before the borrow checker phase.

Re: What to do with C++ modules?

#256
post #246

Earlier quoted context omitted.

After more consideration I think probably your functions don't do anything at all? Is that the joke here? That despite everything you didn't understand why core::mem::drop has that definition and so reading the empty body you assumed that you can just not do anything and that'll work in C++ ?

Are you trolling? Or do you genuinely not understand why it might work in C++? https://godbolt.org/z/58TqTTM37

No, I'm not trolling, I'll give you the benefit of the doubt, try this C++:

https://godbolt.org/z/zM3oxjrfn

and contrast this Rust:

https://rust.godbolt.org/z/1rMYcqY65

In your unique_ptr example what you'd hidden (from me? Or perhaps from yourself) was that we're not destroying the unique_ptr, we're just destroying the Foo, and since the unique_ptr is null the destructor for that will be silent when the scope ends.

Re: What to do with C++ modules?

#257
post #248

Earlier quoted context omitted.

> So what you’re saying is that it takes time, but works out? Probably depends on what you mean by "works out". I don't think GP would agree that delivering a less capable alternative qualifies. For example, one major feature C++0x concepts was supposed to have but got removed was definition-time checking - i.e., checking that your template only used capabilities promised by the concepts it uses, so if you defined a…

C++0x was ~5 years ago. C++26 concepts has more or less everything you mention, and you can try it out with all the major compilers right now.

First lets clear up a thing I've seen a few times on HN probably from people who are new enough to simply not have run into this before.

C++ 0x is what people called the proposed new C++ language standard from about 2005 through 2009 or so under the belief that maybe it would ship in 2008 or 2009. Because you're here, now, you know this didn't end up happening and actually the next standard would be C++ 11. For a little while they even jokingly talked about C++ 0A where A is of course hexadecimal for ten, but by the time it was clear it wouldn't even make 2010 that wasn't funny.

So C++ 0x isn't five years ago, it's about 15-20 years ago and in this context it's about the draft revision of C++ in which for some time the Concepts feature existed, but Bjarne insisted that this feature (which remember is roughly Rust's traits) was not implementable in reasonable time, and frankly was not as much needed as people had believed.

This argument swayed enough committee members that Concepts was ripped back out of the draft document, and so C++ 11 does not have Concepts of any sort. Because this particular history is from the relatively recent past you can go read the proposal documents, there might even be Youtube videos about it.

OK, so, now you at least know what these terms mean when other people use them, that can't hurt.

As to your next claim er, no, not even close. Barry Revzin wrote a really nice paper connecting the dots on this, which probably passed into legend specifically for saying hey C++ 0x Concepts are the same thing as Rust traits. C++ proposal paper P2279 is what you're looking for if that interests you. That'll be less confusing for you now because you know what "C++ 0x" even means.

Now, Barry wrote that paper in the C++ 23 cycle, and we're now at / just past the end of the C++ 26 cycle, but I assure you that nothing relevant has changed. You can't magically have model checking in C++ that's not there. You can't provide concept maps, it's not in the language and so on.

Re: What to do with C++ modules?

#258

Earlier quoted context omitted.

That was my point — with LLMs the progress would not be at the same slope as with people only.

Have there been any successful attempts yet of translating 'idiomatic' C++ to 'idiomatic' Rust for a large codebase that has been developed over 30 years? What does the output look like? Does the code look maintainable (because mechanical solutions to translate from other languages into Rust exist, the result is just not what a human would write or ever want to work on). Are the prompts to guide the LLM shorter than…

Here are a few

https://www.phoronix.com/news/Google-Linux-Binder-In-Rust

https://arxiv.org/abs/2503.23791v1

https://www.darpa.mil/research/programs/translating-all-c-to...

https://link.springer.com/content/pdf/10.1007/s10664-024-105...

> Everybody would be doing it by now

Models and agents have progressed significantly in the last few months. Migrating projects to rust can definitely be a thing in the coming years if there is sufficient motivation. But oftentimes c/c++ devs have aversions to the rust language itself, so the biggest challenge can be an issue of motivation in general.

Re: What to do with C++ modules?

#259
At Waymo we use c++ modules via clang and got the demanded 5x speedup.

As the article mentions, you need a close relationship between the compiler and build system, which Google already has. The google build tooling team got modules to mostly work but only turned them on in limited situations. But we but the bullet and turned them on everywhere, which has sped up compilation of individual files by more than 5x (I forget the exact number).

The remaining problem is that sometimes we get weird compilation errors and have to disable modules for that compilation unit. It's always around templates, and Eigen has been gnarly to get working.

Post reply on HN