My C++ knowledge is pretty weak in this regard but couldn't you link different compilation units together just like you link shared libraries? I mean it sounds like a nightmare from a layout-my-code perspective, but dumb analogy: foo/a/* is compiled as C++11 code and foo/b/ is compiled as C++20 code and foo/bin/ uses both? (Not fun to use.. but possible?)
Is that an ABI thing? I thought all versions up to and including C++23 were ABI compatible.
How does foo/bin use both when foo/a/* and foo/b/ use ABI-incompatible versions of stdlib types, perhaps in their public interfaces? This can easily lead to breakage in interop across foo/a/* and foo/b/ .
> ABI-incompatible versions of stdlib types
libc++ and glibc++ both break ABI less frequently than new versions of C++ come out. As far as I'm aware, libc++ has never released a breaking change to its ABI.
How does Rust do it?
There’s only ever one instance of the standard library when a program is compiled, so an and b cannot depend on different versions of it.
For normal libraries, an and b could depend on different versions, so this could be a problem. The name mangling scheme allows for a “disambiguator” to differentiate the two, I believe that the version is used here but the documentation for it does not say if there’s more than that.
By linking both and not allowing mixing types, i.e. it considers types from a totally unrelated with types from b.
Also, Rust compiles the whole world at once, so any ABI breakage from mixing code from different compiler versions doesn't happen. (Editions are different thing from compiler versions, a single version of the compiler supports multiple editions.)
Rust does not compile the whole world at once. Each crate is compiled separately, and then they’re all linked together at the end.
Yeah, I know, but I mean that it's normal to link together crates compiled with the same compiler, unlike with C, where ABIs are stabler and binary dependencies are more common.
What is the point? C++ is mostly ABI compatible (std::string broke between C++98 and C++11 in GNU - but we can ignore something from 13 years ago). The is very little valid C++11 code that won't build as C++23 without changes (I can't think of anything, but if something exists it is probably something really bad where in C++11 you shouldn't have done that).
Now there is the possibility that someone could come up with a new breaking syntax and want a C++26 marker. However nobody really wants that. In part because C++98 code rebuilt as C++11 often saw a significant runtime improvement. Even today C code built as C++23 probably runs faster than when compiled as C (the exceptions are rare - generally either the code doesn't compile as C++, or it compiles but runs wrong)
There are plenty of things between C++11 and C++23 that have been removed and hence won't compile:
Implicit capture of this in lambdas by copy.
std::iterator removed.
std::uncaught_exception() removed.
throw () exception specification removed.
std::strstream, std::istrstream, and std::ostrstream removed.
std::random_shuffle removed.
std::mem_fun and std::mem_fun_ref, std::bind1st and std::bind2nd removed.
There are numerous other things as well, but this is just off the top of my head.
None of those things I've never used. Many of those are in bad practice for C++11.
Sure. But per your own other posts in this thread, you've got > 10 million lines of "legacy C++". Probably those bad practices are present in that code and not automatically fixable. So switching to compiling everything with a C++23 compiler is every bit as much not an option for you as switching to Rust, no?
If I turn on C++23 and get a handful of errors over those million lines of code I will spend the week or two needed to rewrite just those areas of code. That is much easier than rewriting everything from scratch in rust. Even if we just wrap all needed C++ APIs in C so we can use rust that is a lot of effort before all our frameworks have the needed interfaces (this is however my current plan - it will just be a few years before I have enough wrappers in place that someone can think about Rust!)
Note too that we are reasonably good (some of us are experts) at C++ and not Rust. Like any other human when we first do Rust we will make a mess because we are trying to do things like C++ - I expect to see too much unsafe just to shut up Rust about things that work in C++ instead of figuring out how to do it in safe rust. (there will also be places where unsafe is really needed) I want to start slow with Rust so that as we learn what works we don't have too much awful code.
> Like any other human when we first do Rust we will make a mess because we are trying to do things like C++ - I expect to see too much unsafe just to shut up Rust about things that work in C++
C++ has its own Core Guidelines that are pretty rusty already (to be fair, in more ways than one). There's just no automated compiler enforcement of them.
cppreference say strstream is removed in C++26, not C++23.
I knew they are bad, but I don't think it should be removed.
There is no inherent point, I was just wondering, if it's possible, why people don't use such a homegrown module layout like Rust editions in C++.
I only ever worked in a couple of codebases where we had one standard for everything that was compiled and I suppose that's what 90% of people do, or link static libs, or shared libs, so externalize at an earlier step.
So purely a thought experiment.