The C++ standards committee can standardize a backwards-incompatible "new" C++ for all I care as long as they don't call it C++.
The C++ standards committee can standardize a backwards-incompatible "new" C++ for all I care as long as they don't call it C++.
This x2. It's only C++ if you can optionally refactor random lines of code in a project written in compliance with C++98 using new features and still get a valid program.
Once you mess with the language in a way that your C++98 code is either not supported or requires rewrites or redesigns to comply with the new standard then quite obviously it is not C++ anymore.
Semver matters.
Java is in a similar situation, which is probably why they market the minor version.
The minor version for Java has stopped being used by Java 9.
Our shops won't cut over to something beyond Java 11 until Java 17 (LTS version) hits in a few years. Just happy that we were able to make the jump from 8 to 11.
Poor Android Java developers are now faced with being stuck with a pseudo Android Java subset of Java 8, or migrate to Kotlin.
While any Java library author that wants to share their work with the Android community is faced with the dilemma of keeping two parallel versions of their library, forget about Android, or also convert themselves to Kotlin as well, even if that isn't their thing.
You mean so much of C++'s success is due to backward compatibility with C.
Edit: Formatting.
So there is a path, but it has to take an upgrade-path into account for big legacy projects. In practice, moving to a new compiler can be a big project for companies with larger code bases. Sensible deprecation of features could (and in practice) is part of that.
Even though the standard is quite careful, in practice big C++ projects sometimes rely on non-conforming behavior of the specific compiler version they use. An example is the MSVC template support which allowed constructs that the standard didn't.
Your example is a really poor one. The volatile keyword was only used to provide hints to the compiler on whether or not it could apply some optimizations. Omiting a volatile keyword is perfectly backward compatible, as is compiling code without support for volstile. Thus the only practical consequence of adding/removing random volatile keywords from your source code was how your build could (and not should) be optimized.
That's a far cry from, say, remove malloc().
On MSVC, volatile has traditionally meant something akin to atomic. It still will, regardless of what the Standard says and other compilers do.
"Can't" is a big word when applied to the ISO committee. They would want to consider the magnitude of consequences. Since all implementations would provide a "make like before" switch, consequences would be limited.
No, at best you saw code that expects the compiler to not apply specific optimizations that C++ doesn't suggest or enforce. It's a compiler issue, thus if anything that code needs to be compiled accordingly.
https://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf
class foo {
void i_am_deprecated() volatile;
void i_am_also_deprecated(volatile int);
void i_am_not(volatile char*);
};
Did you ever have a use for this ?The committee does a lot of work to keep the standard compatible with c++ as it is used and this proposal seems to be a good example of them trimming out dead and bloated parts, without negatively impacting existing code.
The original proposal for that deprecation points out a lot of issues. Basically it boils down to the fact that many operations were badly specified, outright misleading, predate the c++ memory model or were artifacts of maintaining the parallel to const that volatile had in C at a large cost and without people actually using it, one example they could track down even noted how it did not behave the same way as primitives would.
In short time, is bad. The more time pass, is good.
The cost of STUPID C/C++/JS behavior is measured in the billons.
Is not the makers of this langs aware? Yes. They know how could be fixed? Sure. Then WHY is not fixed?
Because not considering time in the calculation (and how many MILLONS OF PEOPLE are affect). But today, are DECADES behind of 100% certainty of the cost of this mistakes, and proved beyond doubts that the langs that fixed them ARE better.
In the face of reality and facts, why resist so much?
---
The thing is HOW get out of this mess?
The big irony is that the JS world show how (but not commit with the proper force): Build transpilers. Make "Better C++" that transpile to "BAD C++". Make clear that everyone must move forward, but provide this as partial step.
Make auto converters. Fix damm stupidity like dangling IFs, (seriously some stuff is not brainer). Have a clear vision in how move forward.
And drop the ego. C/c++ not need to turn into Rust, but why believe it could not truly get better?
Now, in the case of C/C++ exist a big trouble in the case of being the "de facto" ABIs for the rest of the world. Apple have the same issue with swift -> ob-c with the case of nullability (which apis never return null even if in theory could?).
Them do annotations to the APIs. This could allow to mechanize the transformations and provide ABI translations that could be injected in the compiler.
For example:
ABI STEP 1 (annotate only):
fn evil():NullableString //Imply NullableString = Option(Str)
[safe(NullTerminatedString == Str)]
fn not_evil(): NullableString
Old code is assumed to be alike evil.ABI STEP 2 (rewrite):
fn ex_evil():Option<Str>
fn not_evil():Str
Then it could autotranslate the calls in demand at compile time, following transformations alike maps.Eventually, when the calls are converted this step is erased and the runtime penalty removed, then all become good.
Less implicit means safer but also more verbose and more cumbersome to write.
Rust priorities safety over everything else, also over productivity too in some case.
Absence of function overloading and automatic type conversion is a good example of that in Rust.
Is it the right choice ? Only time and multi-million line codebase will tell us.
Rust does not provide the facility to strategically obfuscate code at scale like C++-style function overloading does.
// C++
auto f() -> int32_t {
return 1;
}
// Rust
fn f() -> i32 {
return 1;
} fn i = 0;Yes, but no.
When people design a language which they know is going to be incompatible, they tend to go all the way with it. If we're breaking it anyway then might as well do a better standard library interface than the stuff designed in the 90s and all that sort of thing, right? And that's good to have for new projects.
But there is a benefit in having something which makes the smallest possible compatibility-breaking change to fix the defect in the original. So you have a "new language" with a borrow checker, but the standard library functions all have the same names and the same purpose and time complexity as the C and C++ ones, which would allow people to run the existing code through a transpiler which for 80% of the lines can be translated directly to working code in the new language, and produces diagnostic errors for the other 20% that explain what needs to be changed.
Which removes 80% of the work from transitioning an existing codebase to the new language. And then more people do that.
Nevertheless, in Ethernet's case, while it changed backwards incompatibly at the beginning, since then, consumer Ethernet has been backwards compatible all the way from 1990's 10BASE-T (10Mbit) to the still-rare 10GBASE-T (10Gbit). In data centers you have faster variants that require different cables, for routers... but even there I believe the connections to individual servers typically use the old twisted pair.
Maybe that's what Python 3 should have done: don't remove stuff, but just make it discouraged and let a python3only" flag treat them as errors when ready.
What we got was kind of a mess. Because python2 is very often valid python3... But not always.
1. "New C++" would not just be a subset of the syntax of old C++.
2. ABI issues.
Nowadays I'm mildly annoyed if a project is on one of those "ancient" 3 but ≤3.6 Python versions and I can't use the nice features in 3.7+...
No, it is a mess and it was a failure.
It tooks more than 10 years to happen, and even so...Many tools will die with python2 and never be migrated.
If your codebase is not usable anymore because your language evolved. That's a failure.
I can still compile the C's from the 80's today if I want to. Same for Fortran, Same with C++.
Unicode change between 2 and 3 cause behaviour change on your input/output and any serialisation.
Even if your code could have been transpiled properly, the behaviour of your code would have still change, and still introducing bugs
> I can still compile the C's from the 80's today if I want to. Same for Fortran, Same with C++.
I couldn't disagree more. It's a cute trick but not useful that code from 80's is still compilable with a compiler from 40 years later.
There's so many better ways to handle legacy like that, like just freezing the toolchain. Which you've almost certainly long since done if you're actually working with code that old, as the platform it runs on is also frozen.
You can't actually run code from 80's out of the box today (16-bit legacy support has long since stopped being a thing), so why does it matter if it still compiles? And, critically, why does it matter if it compiles with the latest toolchain?
There needs to be a supported sliding window of a generously long time, but it doesn't need to be ~infinite support. That's entirely unreasonable & unnecessary. We don't expect that of any OS, library, etc... so why should we expect it from a compiler & language?
Still a good number of packages you are using right now on your Linux distribution have a core more than 15-20 years old and still they compile only with minor modifications with the last GCC.
Compatibility does matter. It should however not prevent evolution. If handle properly, nothing block us to get a proper versioning and evolution path on the toolchain we use.
And on many aspect C++ up to now has been very successful to do that.
> You can't actually run code from 80's out of the box today
Good C is close to immortal. Doom is from 93, and still you can compile it and run it with the last compiler in 2020 with minor modifications.
So now we're just debating the size of ongoing breakages instead of just their existence.
And no good C is not close to immortal. Good luck compiling K&R C with modern compilers, for example.
If you wrote your 1980s C code:
1. Using the proper C standard. 2. Using the standard library (and perhaps even common Unix libraries). 3. Were careful not to make assumptions about sizes (which, by the language standard, you shouldn't make anyway).
The your code will compile and work just fine. If you used Makefile's to build it, which you very well may have, and you were using a standard (= Unix) system, there's not a bad chance your build system might work too. :-)
You mean the standard that didn't exist until 1989?
> Using the standard library (and perhaps even common Unix libraries)
That's also very late 80s (realistically early 90s) stuff.
Which was still yes a very long time ago that C made all these breaking changes, but it was also a good ~20 years after it's release as well.
Fair point. But K&R C with System V or BSD libraries will probably-kinda-sorta work.
Only if it claimed to be eternally BW compatible. Some languages never made that claim.
To me a language is a dependency like any API, just with a much bigger surface touching my code. I'd say it's the hardest API to replace in any code. "BW compatibility" is just as much a feature as "breaking BW compatibility", I just like languages (or any API really) to be upfront about it's policy toward BW compatibility.
And I've observed a lot of langs change their attitude towards it over time. Especially considering pre-1.0 times, I find a lot of langs happily break BW compatibility in their early days.
Well, just FYI the "new" C++ is not the "old" C++ anymore. Languages "evolve". Try to compile an old program on the new compiler. The same is valid for other languages (C, fortran, perl).
> The C++ standards committee can standardize a backwards-incompatible "new" C++ for all I care as long as they don't call it C++.
They already do this. For C for example you have C89, C93, etc.
Same for C - that old library in C89? Still usable in modern projects.
I am sure there are broken C compilers out there which don’t implement entire language. Heck, I use one sometimes. But I don’t think this proves your point at all.
You need better examples.
Like always on the C and C++ community, "works on my compiler" and "what the standard states about it" is not the same.
This is a real power of C and C++ -- each file gets its own mode. That K&R library you made in ancient time? C++98 classes? All still works and links to the modern stuff. You can be sure that whatever code you wrote today would still be usable, possibly with minor modifications, 20 years later. Sure, the compiler names and build systems will change, but the code would work.
Honestly I would've expected an error with -std=c17 -Wall -pedantic from GCC and Clang since gets() was removed in the C11/C17 standards.