Hacker News new | ask | show | jobs
by heftig 1697 days ago
If the application is using C++17, wouldn't the headers of the C++11 lib then be compiled as C++17, potentially breaking things?

PS: The other way around is more obviously broken, with the C++17 lib headers getting compiled using C++11.

1 comments

Or you make use of the preprocessor or if constexpr, and then have the specific code for each language version.
It's certainly true that if C++ library maintainers are up for the ever-growing maintenance burden, they can all individually deliver the same promise Rust gets out of the box.

This is in practice what the maintainers of the three standard libraries have to do, perhaps one or more of them will offer their opinion about that experience?

The maintainers would have to do it for every new language version that breaks them, though. The edition system keeps old stuff working without any effort.
I don't want to start this discussion thread yet again, but I am a firm believer that edition system only appears to work right now because:

1 - Rust is still quite young and doesn't have 30 years of accumulated editions

2 - There is still only one major Rust compiler

3 - Editions are designed only to work when compiling the whole project, including 3rd party dependencies, from source code within a single build

4 - So far the editions don't have semantic breaking changes across editions, where behaviour changes across the edition border

5 - There is no plan to ever have editions work across ABIs

So "The edition system keeps old stuff working without any effort." might not be true when Rust achieves an adoption scale similar to C and C++, in about 20 years, with several accumulated editions, and a couple of compilers in use.

I might be proven wrong, but that is how I see it today.

> 1 - Rust is still quite young and doesn't have 30 years of accumulated editions

Rust 1.0 was six years ago. When do we start the clock on six years of C++ evolving while also having "old stuff working without any effort" ?

C++ 98 to C++ 03 was five years, and that introduces almost no features at all. C++ 11 was eight years later but it's notoriously incompatible to prior versions of C++. C++ 14 is only three years, C++ 17 has breaking changes, as does C++ 20...

I think C++ 20 should have taken Epochs (yes even at considerable cost to other new features like Concepts) for this reason. I think ten years from now even if Rust has found it can't achieve everything it wants to via editions, this feature will be generally considered to be a good idea, like generics or string literals. Something you need a specific rationale for not including in your general purpose language.

I might be proven wrong too about how far this can go, but I feel like the Rust 2018 and 2021 editions already prove the value of the idea.

For starters epochs could never work in ecosystems that value binary libraries, regardless of possible ABI issues, which is also a reason why Apple went to such an effort to define an ABI alongside language versions.

Lets say you have a noexcept function compiled in C++20 that calls a throws() function, compiled in C++03, which actually ends up throwing, linked together.

What is the runtime supposed to do now?

To which semantics does it follow now?

Call std::unexpected() as it is supposed to do pre-C++14 or call std::terminate() as it should do in C++20?

What about the user defined handler that was configured for such scenario? Which of them gets called, or do both get called, in which order?

Maybe I am doing it more complex that it is, but I see several scenarios from point of view where multiple compilers, binary libraries and semantic changes come into play, editions turn just into another way to define language versions, because they don't cover all possible uses cases how a language might evolve.

Anyway, history will tell how things work out in the end.

> For starters epochs could never work in ecosystems that value binary libraries

Not solving everybody's problem is not the same thing as not solving anybody's problem.

You present subtle considerations which, ignoring the fact that they assume Epochs don't exist in C++ 20 yet ask what Epochs should have done in C++ 20 - might have taken up committee time if Epochs had advanced, and which now can only be answered in the vaguest way, they should definitely have decided on a coherent strategy for resolving such problems.

It is true that for any conceivable change, Hyrum's Law applies, and so it would apply to Epochs just as it does for Rust's editions. Mara's "competition" for writing Rust that gives different results when re-formatted provides examples of the sort of stuff Hyrum's Law invariably breaks. Nobody should be writing non-toy programs like that and in Rust it seems like nobody is. It's a sad fact that too often C++ programs are written in a very fragile way and many of them can and do break with the least provocation.

You can't magically rewrite all those programs, but you can make fragile techniques like SFINAE unattractive to propagate into new programs, and I argue Epochs would have allowed C++ to begin the much harder part of Stroustrup's ever-evolving quest to ship a good programming language - not adding yet more kitchen sinks but removing parts of the language that in hindsight were a bad idea and revisiting old design decisions in the light of what has been learned.

You might well be right, but if the scheme lasts 20 years (and makes it easier to maintain old code during that period), I'd say it's a very good run by PL standards!