> Unimplemented — GCC 16.1 (released 2026-04-30) ships it only as experimental
It will always be experimental before it is standardized, because before standardization the specification could change which means if it was not experimental, GCC had to maintain a standard-incompatible implementation.
Expecting a non-experimental implementation as a requirement for standardization is an impossible goalpost.
tunaredblue 6 hours ago [-]
That is fair, but if you try to sample for usage in real world projects, "reflection" as an example seems to have much more usage than "contracts".
Searching for contract_assert on GitHub, I only found TrenchBroom projects using it; apart from a few projects hiding contract_assert behind a preprocessor macro, which seems like an entirely unintended way to go about contracts.
I also tried to search for "pre(", but only found false positives.
In contrast, there are hundreds of files across repositories on GitHub using std::meta.
Maybe, so; we should all just use Rust in the holy and consecrated name of memory safery. Oh, whoops, Rust is not memory safe, and usage of unsafe is widespread in some algorithmic work, the kind of already-difficult work where the extra difficulty of unsafe worsens matters.
What does that have to do with C++? Enormous pressure was put on C++ to change, in the name of holy memory safety, and C++ contracts was claimed by some to directly address memory safety. And the pressure came in large part from the Rust Foundation and related parties and individuals, such as Steve Klabnik. Funnily enough, Steve Klabnik is very active on C++ forums, and he has "strong forum-voting powers" both here and elsewhere.
That push for holy memory safety was not done in the interest of improving C++ or improving the state of programming. If they, Rust Foundation and company, had had an interest in improving C++, they would instead have tried to add the actually good parts of Rust to C++, namely tagged unions and pattern matching.
Their focus is also in many ways not beneficial to neither Rust nor programming generally, since a lot of energy is spent hiding the actual issues of Rust, thus diverting resources and attention away that could have been spent improving and fixing Rust.
Perhaps Mozilla was right in paying mental-medication-taking Steve Klabnik the least for his community-focused work, after all, his primary focus was not engineering, and he might harbour a burning hatred and envy for actually talented engineers. Or maybe Mozilla should have fired him while they had the chance long ago.
tunaredblue 6 hours ago [-]
Does this contrast what anyone else has found, regarding usage in the wild?
cogman10 17 hours ago [-]
Agreed. I've not liked the contract setup for various reasons. It seems like the proponents of it are mostly there because it scratches an itch in PL PhD studies rather than being an actually useful feature.
I remain unconvinced as why this is a necessary feature over the already existing `assert` statements.
cannonpalms 16 hours ago [-]
At the end, it became very clear that some of the prose came from LLMs. It's a very short survey of other objections. I wonder why he/they reached for an LLM instead of writing it manually.
pjmlp 11 hours ago [-]
Because in circles like HN everyone is proudly telling how they burn Claude tokens?
mort96 8 hours ago [-]
You think Stroustrup's decision making is primarily decided by what's currently hype on HN?
throw-the-towel 5 hours ago [-]
LLM hype is very much stronger than the rest of HN hype.
pjmlp 8 hours ago [-]
Nice way to twist my words, I was replying to the usual paradox in HN to hype about LLMs to code, and complain about the same LLMs to write docs.
mort96 7 hours ago [-]
I don't think I was twisting your words?
> > I wonder why he/they reached for an LLM instead of writing it manually.
> Because in circles like HN everyone is proudly
> telling how they burn Claude tokens?
Or was the "because" not meant to indicate that you're answering the question, were you instead using it as a different rhetorical device? I suppose that could make sense. I think it could've been written a bit more clearly. I really wasn't trying to twist your words.
pjmlp 6 hours ago [-]
Because it is now all the hype, and sites like HN is where the more technically minded folks usually hang around.
So more about the hype in itself and less about HN specifically.
I guess I could have added that part as well.
So yeah, I guess I got a bad reply there, sorry about that.
claiir 16 hours ago [-]
The paper sounds very, very much like Claude
6 hours ago [-]
cowlevel 12 hours ago [-]
> Not tried in major application domains — no shipping production codebase uses
pre/post/contract_assert.
This line is where I realised it's Claude. Also note the emdashes.
Revanche1367 10 hours ago [-]
Did people not read articles and books with em-dashes before LLMs? Why are we pretending nobody used them before? It's one of the first things people learn to typeset properly when learning LaTeX for the first time, not to mention so many books we grew up reading used them regularly.
Propelloni 8 hours ago [-]
I loved em-dashes --- I still do (as you can see, I'm partial to AP style ;)) But most people never understood the difference between hyphens, en-dashes and em-dashes in the first place. Or that The King's English uses en-dashes where US English uses em-dashes. Merriam-Webster has a short and amusing -- to me -- article on this topic [1]. So all kinds of "dashes" are rolled into the "em-dash is an AI tell" hysteria.
That LLMs use them all the time is also a good indicator that there are alot to be found in the training material.
I routinely use em dashes. They are easy to type on Mac and Linux. Only Windows makes it a hurdle.
1718627440 6 hours ago [-]
Nowadays it's also just Super-(Shift-)Hyphen on MS Windows.
jisoaprudo 13 hours ago [-]
[flagged]
digitalPhonix 16 hours ago [-]
I think this is putting too much weight on this event and Bjarne’s position on contracts.
Bjarne’s opposition to contracts might have tipped the scale but there is definitely growing weariness (and wariness) about large half-baked features that are left as exercises to the implementors (looking at you modules).
Ignoring that historical context when analysing this vote seems like a mistake.
StellarScience 18 hours ago [-]
This is a well-written and quite diplomatic summary by Herb Sutter. I'm not plugged in enough to be sure he's correct that Stroustrup's opposition was the main reason the C++26 vote failed where others have passed, but it sounds plausible.
It also lists 6 possible paths forward for C++26 with pros and cons. I think they are roughly:
A. Skip an official C++26 standard but roll these features into C++29.
B. Remove contracts from C++26 and pass it.
C. Say "please" and vote again.
D. Tweak contracts regarding virtual functions and vote again.
E. Pass C++26 as many different countries' national standards rather than an international standard.
F. Do E and also consider leaving ISO and moving to ANSI/INCITS instead.
aw1621107 17 hours ago [-]
I think "guaranteed contract enforcement" should be added to item D since that is explicitly called out as the only technical proposal that would change some NB votes from no to yes.
bluGill 16 hours ago [-]
What does guaranteed enforcement mean? Is it worth the trade-offs? There's a reason why most code turns assert off in production and only does it in debug builds. A lot of checks are certainly possible to run, but they're unreasonably expensive to run and so if the code is trusted to work, you wouldn't want to check that it's working correctly.
If, on the other hand, you mean only that, regardless of the status of a contract, if the compiler can detect that it would be violated, it must have failed to compile, I guess that would be all for that. On the other hand, the state of theorem provers that are able to prove things will and won't work is ... evolving. There will a lot of people be frustrated when they upgrade their compiler to a minor point release and suddenly a lot of code fails to compile because it always was broken but likely in an obscure situation that never happens in the real world.
aw1621107 14 hours ago [-]
> What does guaranteed enforcement mean?
I'm not sure I can express it better than the proposal to add the corresponding feature [0]:
> This extension addresses the Romanian National Body's (NB) concern by enabling the writing of an individual contract assertion that guarantees the program execution will not continue past the contract assertion if it is violated, regardless of the semantics of other contract assertions. This addition to the C++26 Contracts facility allows reliable use of enforced contract assertions in large codebases with mixed contract semantics and also in hardened libraries.
> Is it worth the trade-offs?
Apparently some people/NBs feel quite strongly that it is.
> There's a reason why most code turns assert off in production and only does it in debug builds.
There's also a reason some codebases define asserts that aren't turned off in production in addition to debug-only asserts. The proposal lists multiple under Section 3.1 Existing Practice.
> and so if the code is trusted to work, you wouldn't want to check that it's working correctly.
Right, but sometimes you might think the consequences of such blind trust being misplaced are worse than the performance hit.
Static detection of impossible-to-satisfy contract conditions would be interesting, but as you say the technology is probably not ready for the kind of widespread use that inclusion in C++ would entail.
I see. Somehow I missed that paper. I've seen it referred to, but never in a form where I could find it.
And now I'm even more confused. Why is this so critical that we can't say we're going to put it in another next version of the standard? Compile is regularly see things in the future version of standards and them implement early. I'm not disagreeing with the paper. I'm disagreeing that this is so critical it needs to abort the whole process.
steveklabnik 2 hours ago [-]
> Why is this so critical that we can't say we're going to put it in another next version of the standard?
This feature was first proposed in 2004. In 2018, they were added to the draft of the standard, and then removed in 2019. So that already has been happening, for over a decade.
Part of the reason this is coming to a head is that it's already been a long time. Another reason is that some see contracts as fitting into the safety story for C++. Part of it is because, well, standards are done by the people that show up, and the people who show up care about this.
> I'm disagreeing that this is so critical it needs to abort the whole process.
It's a byproduct of how the process works. There are a series of votes, and they're not done by the same people. Some people voted yes to put them in, and then the vote after involved people voting no, they don't think they're good enough to put in. It is not so much that "this is so critical that it needs to abort the whole process," so much as it is "the final vote is the time when those people get to express their support or dissent." One of the proposals in the paper is that they could remove this feature, and then the rest would likely move forward. It will only hold up the entire thing if the people who are pro this feature landing decide that it's worth holding everything else up for.
bluGill 29 minutes ago [-]
Contracts failed in the past because it was so large. This was supposed to be a minimum viable proposal that would be extended over time. But one small group is demanding their extension now anyway.
More and more I'm on the side of those who are point at the 'no' votes as babies who can't work together. This is not a new thing and your preferred action isn't the best compromise, grow up. I know that is insulting, but it seems well deserved
I have a feeling that the paper isn't even a good way to solve their problem, but I can't quite figure out what would be better.
aw1621107 4 hours ago [-]
I was in the same boat as you with respect to that paper. I only know its number because Herb mentioned it.
The only red-string-on-a-cork-board I can connect is between guaranteed enforcement and the design decision that "contract assertions must not be used for error handling and input validation". The latter would seem to rule out guaranteed enforcement now and in the future and EWG apparently voted against P3911 back in January [0], so perhaps they think that they won't ever see guaranteed enforcement if contracts is left in the standard as-is.
That's all quite speculative, though, so take that with an appropriately-sized grain of salt/
I haven't really paid attention to C++ in a while (last neat feature I saw was concepts). Usually I kind of enjoy the weird, expressive code golf you can write with the new features. For example I tried out using concepts to ensure Matrix dimensions were compatible with the desired operation. Not really that useful, but was a neat thought experiment.
But these proposed contracts... I just don't really see much benefit it offers over just explicitly writing your own assertions.
I suppose you can see the requirements in the declarations, but I would wager that fancy modern C++ declarations quickly become so long and verbose that you'd get quickly fatigued from reading them. Perhaps in the LLM era they are more useful?
Routine8502 18 hours ago [-]
As someone who spent a few weeks trying to get into C++ (pre-LLM, so maybe it's better now?) and kind of just gave up out of confusion, I really found it challenging to deal with the multiple different ways to do something. I mean, which pointer should I use? How should I iterate? I'm sure there's an answer to this, but I just found it easier to go back to python and hit up rust when I needed it.
It seems like part of the concern is that the feature needs to be shipped right the first time because it'll live forever. Perhaps allowing features to be deprecated and then removed could help?
But idk, I haven't written anything that lasted 36 years, so maybe the current approach is for the best!
kllrnohj 17 hours ago [-]
Does the existence of PEP 572 not similarly result in being paralyzed and overwhelmed at the number of ways to do something being greater than 1?
C++ definitely has complexity, but I'm surprised by the two examples specifically chosen. Which pointer? C++ only has 2: unique_ptr and shared_ptr (or 2.5 if you want to include weak_ptr but that necessarily means you already chose strong_ptr first). While this might be a complicated choice if you're just comparing to Python, but it shouldn't be if you're familiar with Rust since Rust has you make the same choice.
And then "how should I iterate" is similarly the same as any other language? Either a for or a for-each loop?
There's definitely baggage from 38 years of lessons learned, to be sure, just those examples are odd choices
TheOtherHobbes 16 hours ago [-]
You've already mentioned four pointer types which are separate to the original plain vanilla pointer concept.
When I started C++ nearly 15 years ago this was already a huge problem. I bought some books and looked up online references and after a while I discovered that both were already out of date.
C++ is a chimera. And it hasn't improved since.
Other languages are far more stable, conceptually. New features rarely undermine or reinvent the older ones.
C++ is unique in the way it keeps modifying its own core. There is no formal deprecation or EOL process, so the language is more like an archaeological dig than a living standard.
kllrnohj 16 hours ago [-]
> There is no formal deprecation or EOL process
Yes there is or we'd have been talking about std::auto_ptr as well.
> New features rarely undermine or reinvent the older ones.
Many languages have mistakes they've later tried to sweep under the rug. JavaScript arrow functions trying to convince everyone that bind(this) wasn't ever a thing, for example.
C++, for whatever reason, is consistently the only language where people are determined to always dig up the skeletons and pretend they are at all still relevant. It's not unique in having skeletons. It's not unique in having language spec mistakes that can't realistically be changed, just ammended with a newer, better alternative.
But like the saying goes, there are only two kinds of languages: the ones people complain about and the ones nobody uses
jeltz 12 hours ago [-]
C++ is not unique in having historic spec mistakes but it has by far the most of them which are still relevant today of all languages I have used. Maybe Perl or PHP come a bit close, but I doubt it.
cowlevel 12 hours ago [-]
Perl hasn't evolved in a while but PHP is definitely full of historic mistakes, dating all the way back to the first versions using strlen as a hash for function name lookup.
zzzoom 15 hours ago [-]
> And then "how should I iterate" is similarly the same as any other language? Either a for or a for-each loop?
for (ignoring do and while) and foreach loops, std::for_each, ranges for_each at the very least
kllrnohj 15 hours ago [-]
...which is the same as nearly every other language? What language doesn't have that same collection of stuff?
Java: for, for-each, do-while with iterator, list.forEach(..), list.stream().forEach(..), etc...
zzzoom 2 hours ago [-]
Python?
StilesCrisis 17 hours ago [-]
Don't forget * (true pointer) and & (called a reference, more honestly a pointer that can't be repointed, except with UB it can _totally_ get repointed).
Vaushite 14 hours ago [-]
Knowing the story behind a decision like that is worth a thousand spec clauses.
When the language got operator overloading there was the question of how to convert the arguments from the operator itself to its implementation. You wanted to write a+b, not &a+&b but most versions of operator+ were going to want const pointers for efficiency. One option was to make the & implicit, another was to introduce a type of argument that didn't need & but acted like a pointer. So references were born.
I ignore people who advise to use references when something can't be null. A null reference is UB just like a null pointer, it just shifts where the UB is, but the compiler is likely to produce the same code either way and the program is just as likely to crash. Instead, I use pointers to make it obvious that something is a pointer, and references when it should be invisible, just like with operator overloading.
rerdavies 14 hours ago [-]
The source of the UB is dereferncing a null pointer. I don't think it's possible to obtain a null reference otherwise. I, on the other hand, ignore people who advise against using references for parameters that can't be nullable. Particularly const references, which provide potentially massive performance improvements, and are a core idiom in C++.
cowlevel 12 hours ago [-]
Somewhere you have a null and somewhere you want to call a function on it (by mistake). Whether you call it through the pointer or convert the pointer to a reference and then call it through the reference makes no difference, the program still has UB. You can't even argue that the UB occurs at a different point in the program - that makes no difference because UB is allowed to time-travel.
Didn't they say they use references when the pointer/reference should be invisible?
aw1621107 12 hours ago [-]
> Particularly const references, which provide potentially massive performance improvements
My understanding was that const references don't provide that much in the way of optimization opportunities (if any?) due to aliasing and the existence of const_cast.
cowlevel 12 hours ago [-]
It's not about that, it's about avoiding copying to a function parameter. If you want a function that adds a bunch of integers, you should write it as "int sum(vector<int> const&)" rather than "int sum(vector<int>)" because the latter will copy the whole array of numbers just to sum them and delete the copy, when you could have summed the original array with no downside. Arguably it should be span<int> though now that exists.
aw1621107 11 hours ago [-]
If you just want to avoid a copy without adding a null state then it's the reference bit that makes all the difference. Whether that reference is a const reference or not does not matter for optimization, I think.
cowlevel 10 hours ago [-]
If you make it a non-const reference the compiler won't let you pass a result of another function call such as sum(get_daily_prices())
aw1621107 10 hours ago [-]
Sure, but I think that has less to do with optimizations and more to do with avoiding potential footguns. The standard could, in principle, allow temporaries to bind to non-const references (and IIRC older versions of Visual Studio did do such a thing).
And even without such a change, such a restriction is pretty easily worked around without a const reference with something like T&& temp = get_daily_prices(); sum(temp);. I don't think that'll result in different codegen than either passing a temporary to a const ref or allowing binding a temporary to a non-const ref.
Gibbon1 9 hours ago [-]
Things I read recently makes me think that default target for stuff like that is a manky compiler that's half a step above macro assembler. AKA it's much faster if your compiler is dumb as rocks and usually not with actual compilers.
dwattttt 9 hours ago [-]
One of the first production C++ codebases I worked on had helpers:
Type& GetReference(Type*);
(Type is a placeholder, it was not templated). It worked exactly how you'd fear it would, and as a result we had to chase down null dereferences of our "can't be null" references all over the codebase.
EDIT: by "exactly how you fear it would", it just did a dereference and return. It didn't check for null, didn't throw, and couldn't otherwise signal a failure.
senthil_rajasek 17 hours ago [-]
Made me LOL
Vaushite 14 hours ago [-]
C++ has to be approached as a grab bag of useful parts, not a coherent whole. It's somewhat akin to Python if Python modules were C++ language features. It's said that nobody knows all of C++, even its creators.
Do you know C? Everything that works in C works in C++, modulo a few minor syntactic changes (void* doesn't implicitly convert). You can get acquainted to C++ features on an as-needed basis. Other people will surely disagree with me on this.
With pointer types in particular, I'd say use C-style pointers long enough to know how frustrating they are but also how they work. Then you'll know what unique_ptr and shared_ptr are doing to help you. (And those are the only two you need 99% if the time. weak_ptr is a spin-off of shared_ptr that you'll know if you need it. observer_ptr is just stupid ivory-tower stuff.)
rerdavies 14 hours ago [-]
It's probably nice to know WHY you might need weak_ptr.
cowlevel 12 hours ago [-]
Explanation: shared_ptr is an implementation of "reference counting". All shared_ptrs to the same object collaborate to know how many of them exist (it's just a ++ on creation of one, -- on destruction of one) and when the last one is destroyed it also destroys the object that's pointed to.
weak_ptr is like shared_ptr but doesn't add to the count. When the last shared_ptr is destroyed it destroys the object even if there are still weak_ptrs. Any weak_ptrs pointing to that object become null. I won't dive into how that's actually implemented. Obviously it costs some CPU cycles to make that happen, so you don't see shared_ptr or weak_ptr a lot in code that's written with a performance mindset. Although you're still getting 90% of the performance benefit by writing C++ instead of JS even if it's "inefficient" C++.
I agree with GP's point and add, if this isn't something you need to do, then don't even think about it. C++ is like a toolbox with a bunch of tools. I don't study all the tools before building a table, I look up how to build a table, and then see if the tools are in my toolbox. Studying the triangle screwdriver would be a waste of time and only confuse me more, unless I'm trying to drive triangle screws. Only when I need to drive a triangle screw then I can look for the triangle screwdriver.
pjmlp 11 hours ago [-]
For the same reason you need weakref in Python, to handle circular references in memory managed via reference counting GC algorithm.
Anyone that thinks Python is "simple", to come back to some of the suggestions on how it is easier than C++, they really should learn the language reference, standard library, and CPython FFI manuals.
aleph_minus_one 9 hours ago [-]
>
Anyone that thinks Python is "simple", to come back to some of the suggestions on how it is easier than C++, they really should learn the language reference, standard library, and CPython FFI manuals.
Python is more "simple" in the sense that
- it is more forgiving with respect to badly written code,
- it has collected less historical baggage than C++.
Otherwise I agree.
pjmlp 9 hours ago [-]
It really isn't less forgiving, it just happens that as a dynamic language, it blows up at runtime instead of failing to compile.
Yeah, we all know how cleaning up Python has worked out, and unfortunately a few ecosystems failed to learn from it as well, e.g. Java 8 => 9, .NET Framework => Core.
MathMonkeyMan 17 hours ago [-]
Features are deprecated and removed. It's uncommon but it happens when a new feature makes all use of the old feature unnecessary. Usually it's deprecated for a few versions and then removed some years later. You can always compile old code against an old standard.
C++ does have many ways to do anything. Most of that is historical, or due to features and library facilities with overlapping capabilities, or inherent to multi-paradigm programming languages.
Every C++ project is written in its own language. Its own "house flavor." This is true of all languages, but is particularly stark for a language as old, complicated, and powerful as C++.
rickstanley 17 hours ago [-]
I share the same sentiment and experience from trying to get into C++. I bought "A Tour of C++" (2022, Stroustrup), I read it back to back, and I thought to myself "it's not so bad, seems quite nice actually, specially the modules part"... oh boy. After 2 weeks writing a HTTP requests CLI tool I was feeling really demotivated, I gave up and went to rust, for no special reason, I just had it queued up after reading "The Rust Programming Language" book.
> pre-LLM, so maybe it's better now?
I came back to the toy tool some time later and used GLM 4.x to implement it further. I had a good experience with it and I understood the code it generated. From my experience, in general, LLM is a good mentor, if you are willing to ingest the content step by step. For me, it is no different from when I used StackOverflow (and other forums) to try and ask how a thing is done.
rerdavies 14 hours ago [-]
Agree with that. I'm a veteran user of C++, and I'm constantly finding really nice idioms in AI-generated code that I end up using myself.
cowlevel 12 hours ago [-]
One of the interesting things about C++ is that things that are language features in other languages are idioms in C++.
hasley 11 hours ago [-]
When they are turned into features people complain about C++ becoming too complex. So, what can you do...?
hasley 11 hours ago [-]
What exactly was your problem?
And was it the language itself or the libraries?
hasley 11 hours ago [-]
"I mean, which pointer should I use? How should I iterate? I'm sure there's an answer to this, but I just found it easier to go back to python and hit up rust when I needed it."
You can of course use Python. But we are talking about languages with different applications. You want fast development hand have no expectations on speed? Use Python! You want to control your computer to get maximum performance with a safe type system? Use C++!
Since you are already talking about pointers: In Python you are not even given the chance to do all the stuff you can do in C++. You have to rely on garbage collection (and "del"). That is an entirely different thing than C++ where you exactly control how long your objects should live.
For the pointers (order I would suggest):
1) No pointers, use references whenever possible
2) Use std::unique_ptr
3) Use std::shared_ptr
You can also try to use shared_ptr all the time if it makes your transition from Python more easy. It is not optimal, but it may get you started.
And do not start wrapping your head around rvalue references right from the beginning. This is a very special topic, which you can ignore as a beginner.
pjmlp 11 hours ago [-]
> You can of course use Python.
Which also has plenty of way to do the same thing.
People often mistake the easiness to write Hello World, with the real expressiveness that is available in any given language.
eluru 15 hours ago [-]
I studies for some descent while with the objective of using unreal engine, then i found out everyone was just using blue prints so not even them liked CPP
on_the_train 15 hours ago [-]
> which pointer should I use?
The answer is almost always: no pointer
cowlevel 12 hours ago [-]
True, and that advice is useful to people coming from JVM languages. But you do often need pointers.
on_the_train 2 hours ago [-]
I'd say pointers are very rare in proper code.
yodsanklai 17 hours ago [-]
You're very diplomatic (yet downvoted), C++ is an abomination of a language. It just puts too much accidental cognitive load on developers. I understand that
- it shines for some tasks where Rust isn't capable enough
- it's impossible to get rid of because of all the code so we may as well modernize it
- there's an active community of people who built a career of being C++ experts and have no interest to see the language disappears.
Even in the LLM era, I find it's difficult to code in C++. The language has so many corner cases that LLMs make mistakes. My experience 6 months ago was that the code written by my agent had tons of complex linter warning (exceptions, lambda leaking references, futures whatever... that I just can't avoid because the codebase mixes all of this). Whenever possible, it's probably time to either modernize it or port it to Rust, component by component, until the C++ part is small or inexistant.
stackghost 11 hours ago [-]
It’s been my experience that pair programming specifically in C++ with an LLM rather than having it write the code is a great way to stay sharp.
rerdavies 14 hours ago [-]
Maye you need a better AI. Just sayin'. My AI (Claude) doesn't make mistakes. Ok. It doesn't always think strategically, or factor well. But it certainly doesn't struggle with language mechanics.
Modern best practice for C++ is to crank the warnings to maximum, and to treat warnings as errors. You absolutely should treat linter-like warnings as an error, because they invariably are. So you know.
mathisfun123 17 hours ago [-]
> As someone who spent a few weeks trying to get into C++ and kind of just gave up out of confusion
what should be conclude from this? this is like saying you tried to become a professional trapeze artist for a couple of days. C++ is complex and deep. what did you seriously hope to accomplish in a "few weeks"?
i started writing C++ professionally 4 years ago, i.e., i write it every single day at $JOB. there are still large parts of the language i'm not familiar with.
zahlman 16 hours ago [-]
> what should be conclude from this? … C++ is complex and deep.
Yes, that's the point. Much of this complexity would not be necessary to achieve the same things, given the ability to redesign from scratch.
cowlevel 12 hours ago [-]
Maybe. Many people have tried, but only Rust has gotten anywhere close, and Rust can hardly be described as "not complex".
kazinator 16 hours ago [-]
36 years of sustained agreement is not good; it means nobody is saying no to anything, and you have a giant, dirty snowball rolling down a mountain.
dwaite 16 hours ago [-]
I don't think this is a correct take. For instance, the earlier incarnation of this feature got pulled from c++20.
rerdavies 13 hours ago [-]
And C++23. If only they had said no one more time.
jeremyjh 6 hours ago [-]
When reading the TFA, I noticed several examples they gave of individual features being pulled in order to pass the standard.
kikoreis 17 hours ago [-]
Just stopped by to say Sutter is not only right to be reiterating Bjarne's position here, he is also the author of IMO the most impactful paper regarding the progress of hardware performance and the shift to concurrent execution: https://www.cs.utexas.edu/~lin/cs380p/Free_Lunch.pdf
Calavar 17 hours ago [-]
C++ committee members (mainly Boehm, but also Stroutstrup) also deserve a lot of credit for giving us a well specified memory model for concurrency outside of functional languages. Rust basically copy/pasted the C++11 memory model wholesale. Rust's fearless concurrency owes a lot to standing on the shoulders of giants.
cogman10 17 hours ago [-]
C++11 borrowed heavily from the Java memory model that came before it.
It's basically everyone learning from everyone else on what works and what doesn't work.
plorkyeran 14 hours ago [-]
Java deserve a lot of the credit for the happens-before concept that is the foundation of both its memory model and C++'s, but it can't express relaxed access and figuring out how to fit that in was a really big deal.
tialaramex 16 hours ago [-]
I don't think fearless concurrency is strongly related to the atomic memory ordering model.
C++ 11 wants to model two non-trivial orderings, Acquire-Release and Consume-Release, but only Acquire-Release is actually usable. So yes, C and Rust both also choose to offer Acquire-Release ordering like C++ but it's also clear that the universe of possibilities is actually smaller than WG21 realised when C++ 11 was developed.
If on your first random stab you guess 65537 is prime, you're correct and you might foolishly assume all those Fermat Numbers are prime and then try say, 4294967297. Nope, that's divisible by 641 for some reason. There are only Five of these Fermat Primes so far as we know, they weren't common after all.
haberman 15 hours ago [-]
My understanding is that Consume is actually a desirable semantic that models what algorithms often want, and would allow for more optimization than Acquire if implemented properly, but that its failure was due almost entirely to it being difficult to implement correctly in compilers. In particular, the semantic is difficult to preserve across all compiler passes, especially given that existing compilers are essentially 20-40 years of accumulated optimizations that were never designed to preserve this semantic.
I sometimes wonder how difficult it would be for a compiler that was designed from the outset to implement Consume correctly.
colanderman 16 hours ago [-]
Nit: Rust currently adheres to C++20 memory model. At least one notable difference from earlier versions which tripped me up recently is that release sequences aren't extended by further writes.
blltprfmnk 17 hours ago [-]
I’m not sure where you draw the conclusion that this was impactful. Intel had been sounding the alarm for at least a couple years at that point (longer if you were privy to private communication with them). Not to mention that C++ failed pretty miserably to enable safe concurrent and parallel programming for the masses, and the industry as a whole still struggles as a result.
gavinray 17 hours ago [-]
Languages have not yet evolved to multi-core properly IMO
I've sketched what I think an ideal "language of today" would look like, and one of the core tenets is making concurrent code explicit and part of the design surface.
You might imagine a webserver with main code like:
spawn(on_core: 0) {
await receive_packet(input)
}
Or iterating over "num_cpus" and doing the same thing, with hashing based on CPU number for shared-memory resources.
xyzzy_plugh 17 hours ago [-]
The problem is that when you build at this layer, you end up writing far more scheduling code than business logic. Eventually you've built the abstractions we already use today.
The vast, vast majority of software, and software developers, simply do not care about core affinity, NUMA, noisy neighbors, etc.
Even on systems or situations where this matters (massive number of cores and memory, multiple sockets, thousands of threads, etc.) the juice is rarely worth the squeeze.
Doubly so when you end up being I/O bound anyways.
Nearly every software developers wants their software to work across multiple deployment targets. Maybe you just target x86-64, and you don't care about the number of CPUs because you'll be upgrading your servers every couple of years.
No one wants to deal with difficult-to-reproduce issues related to scheduling in niche configurations. It's much more efficient for runtime or compiler engineers to solve these problems for us, leveraging the vast amount of resources of corporations to develop and test these features. Then you have a place your code can live happily ignorant of its runtime constraints.
And that, my friend, is the beauty of our industry.
rerdavies 14 hours ago [-]
... until you end up writing code that runs on ARM, which has weak memory ordering.
tancop 11 hours ago [-]
Even better with structured concurrency and no function coloring like Verse:
The receive functions are async so they can only be used inside an async context, like the one created by race. Race is a keyword from Verse that returns the result of the first finished task and cancels the other.
17 hours ago [-]
jmyeet 15 hours ago [-]
I disagree. In a world of different architectures, out-of-order execution, asymmetric cores, branch prediction, per-core caching and information leakage between threads and the branch not taken, my opinion is firmly that most people shouldn't be writing multithreaded code because it is almost impossible to get it correct and safe.
The effects can be subtle and lurk for years until a seemingly unrelated change exposes them. It starts with optimizations like instead of spawning a thread, you use a thread pool, possibly abstracted as some kind of executor service. Other code might use different thread pools to isolate them because each pool has its own limits on the number of threads. Some might grow but usually they won't.
Until one day you end up with thread starvation and a deadlock through a series of benign seeming optimizations. There are threads around but not in the right pools and the entire thing grinds to a halt.
Cooperative async/await on a single thread is the ideal solution for most use cases, particularly with complete environment teardown between requests. Yes, this is basically the PHP model.
hora 17 hours ago [-]
That paper turned out to be enterily wrong, not only did single core performance keep increasing significantly, today most software is being written with almost no concurrency in mind
ChrisMarshallNY 16 hours ago [-]
That's because concurrency is really in the SDK or stdlib for the language or platform.
In my opinion, that's really the best place for it. From what I understand, that's always been FORTRAN's secret sauce.
I've been doing threaded code since Day One (Machine Code), and have gotten it wrong, quite often. There are a million things that can cause concurrent code to actually perform worse than single-thread code.
These days, I usually just let the platform pick the threads, and generally write code that will play along.
stingraycharles 16 hours ago [-]
The only software that is written without concurrency in mind is software that uses very few resources.
Anything else heavily uses concurrency in all kinds of ways.
hora 15 hours ago [-]
which turns out to be the vast majority of software, because contrary to what the author of the paper predicted, single thread performance ended up being more than good enough (and not the bottleneck)
bolangi 6 hours ago [-]
Nice that perl got a mention, but it is not especially nuanced. Raku is not a fork of perl, it's a new language. That is why it got a new name. It was intended to be backward compatible, just didn't work out that way. However, Raku's FFI lets Raku code call into perl, and vice versa.
account42 6 hours ago [-]
Raku was originally called Perl 6 though. It is a fork, not an unrelated new language.
lizmat 4 hours ago [-]
Is Perl a fork of sed and awk?
account42 4 hours ago [-]
Was Perl originally developed as the next iteration of either of those? Why are you being disingenuous?
socalgal2 16 hours ago [-]
I'm sure I'm not the only one but I feel like C++ is over/done. I work in a C++ code base and have been doing C++ for > 20 years and to me at least, the writing is on the wall.
1. C++ is unsafe. Bjarne keeps giving talks that effectively say "use it perfectly and don't make any mistakes and it's safe". That's not useful anymore. In a world where LLMs can find every mistake to exploit it, all the C++ projects are struggling to keep up and keeping them in C++ is basically guaranteeing there will be more exploits in the future. Yes, not every bug gets solved by switching to a safer language but reducing the attack surface in the new reality is no longer something that can be put off.
2. LLMs can re-write. The previous arguments used to be "there are C++ legacy code bases so C++ will never die". That was a valid argument before an LLM would just rewrite it all. I get people will say they aren't perfect, neither are humans though. Further they get better all the time, and we see their progress. People pointing an LLM at some project and it magically making it work on some other platform etc... It's clear it's happening.
j4k0bfr 12 hours ago [-]
I'd like to live in a world where an LLM can exhaustively verify all C++, and where porting C++ codebases is safe and easy. However I'm not fully confident we're there yet.
Plus, there are a lot of pros to C++ which aren't so easily waved aside. The breadth and duration of support makes it almost impossible to kill quickly, imo. If a magical LLM bullet shot C++ dead tomorrow, many established orgs and projects would keep it rolling. It also sits in a funny spot where you can get pretty good performance from not-great code. And it is incredibly fun to write! Reading it is... another matter ;).
Edit: I'm sure dumping piles of money into abliterated models can get you quite far. ROI and correctness are the parts I'm still sus about, however I hope to be proved wrong.
rerdavies 13 hours ago [-]
On the other hand, LLMs can (and do) also find every mistake and fix it.
I'm not ashamed to admit that I occasionally ask my LLM to find and fix all the bugs in a file. And not ashamed to admit that it often does. Most usually algorithmic problems, not memory problems, fwiw, because I use modern C++.
nmfisher 14 hours ago [-]
I recoil when I look at the roadmap for C++2x (most of it, anyway), it's a bloated monster and I suspect the language is on its last legs.
It will probably take a lot longer to die than I expect, though, too many legacy third party libraries are written in C++ and most people don't really like the syntax for the logical alternative (Rust).
rerdavies 13 hours ago [-]
I was actually really impressed with Swift, which seems very much like a C++ with all the historical cruft and awfulness removed.
eluru 15 hours ago [-]
As obvious as they sound i havent tought about those points before, they do make sense
tsss 8 hours ago [-]
I was at a Bjarne Stroustrup talk 2 years ago and it was pretty embarrassing. He was dodging Rust questions all day long, giving nothing but non-answers that would make any politician proud. But perhaps "dodging" is the wrong word here; more like "being run over". He has no vision for the future of C++ besides "it's its own thing" and "everyone is already using it". His best idea is to publish a compiler preset that disables the most dangerous features.
dvh 13 hours ago [-]
Time to remove c++ from your resumes old men!
auto fib = [](this auto self, int n) -> int { return n < 2 ? n : self(n-1) + self(n-2); };
auto v = std::views::iota(0, 20) | std::views::transform(fib) | std::ranges::to<std::vector>();
for (auto&& [i, x] : v | std::views::enumerate) std::println("{} -> {}", i, x);
auto add = []<typename... Ts>(Ts&&... ts) { return (... + ts); };
static_assert(add(1, 2, 3) == 6 && requires { std::format("{}", 'x'); });
dist-epoch 4 hours ago [-]
Why are you writing Perl, in a post about C++?
mystifyingpoi 10 hours ago [-]
Thanks, I hate it.
qiqitori 18 hours ago [-]
I'm amazed. Someone somewhere conceived of a feature, and it wasn't put into C++!
bluGill 16 hours ago [-]
There are a lot of ideas that don't make it into C++. You just don't hear about them because quite obviously you are not paying even a slight amount of attention to what ideas people propose.
account42 8 hours ago [-]
> Fact 1: WG21 has strong consensus for contracts
It very obviously does not. Stating what you want to be true as "facts" does not make it so but rather discredits the one making the assertion.
kazinator 16 hours ago [-]
Not only did Kernighan and Ritchie not update the C book for a standard newer than C89, Kernighan underscored that by updating the The Awk Book in 2023 (with Aho and Weinberger: the other two letters in Awk). As if to say C is so far gone that even Awk is more worth writing about.
bluGill 16 hours ago [-]
KNR have written a lot of books that they have not updated over the years.
eluru 14 hours ago [-]
Before reading it i was sure this was going to be about how the PHP creator warned everyone hes language was for blogging, then we had an apocalipse
mont_tag 13 hours ago [-]
[flagged]
wang_li 18 hours ago [-]
“Owners”? No one owns a language. People will do what they find pragmatic, practical and necessary. A committee who thinks they own a programming language has become pretentious and misunderstands their relationship with developers.
Arainach 18 hours ago [-]
You're arguing semantics. The committee owns the C++ standard and its future. It's not pretentious - not having such a governing body leads to either divergence or stagnation, both of which are usually fatal.
FabCH 10 hours ago [-]
Isn't the entire point of the article that they _don't_? They say they do, but when the chips are down, the actual owner sunk their proposal "easily".
And the article also mentions that divergence is a real possibility in situations like this.
account42 8 hours ago [-]
Actually the future of the language is owned by the compilers implementing it and ultimately by the users choosing which compilers to use. The committee is a mere formality that can and will ignored as needed. For example, C++ has had #pragma once for decades even though the committee still refuses to admit it.
muvlon 17 hours ago [-]
No, ISO owns the standard, and they just shot down the committee's proposed draft.
kllrnohj 16 hours ago [-]
The committee is part if ISO. Larger ISO shot down smaller ISO. Both are under the same system. WG21 is just the C++ subgroup of ISO.
rudedogg 18 hours ago [-]
> not having such a governing body leads to either divergence or stagnation
Or you do the BDFL model like Python, D, Zig, Odin, etc.
I think it works better. A language that reflects the vision of an individual deeply thinking about the interactions of language features, and being able to say "no" to anyone/everyone has many benefits.
Committees make me think of the Web, C++, Swift, etc., and they have a lot of "odd" decisions that have had a heavy cost. Swift has https://www.swift.org/swift-evolution/, but a lot of ideas with minority support were pushed through by Apple (for SwiftUI mainly), against overwhelming community feedback.
And the Web has had a lot of "duds" when you think of WebGPU, WASM (not saying it's bad, but people clearly want to stop writing TS/JS and they haven't made that a reality yet, at least in a way I'd call "successful"), etc.. Oh and DRM in the browser sucks. I forget the details but I was goofing around with FreeBSD Desktop and couldn't get various things to work due to some browser DRM bullshit. https://en.wikipedia.org/wiki/Widevine if curious.
rerdavies 13 hours ago [-]
The Python 2/Python 3 things was pretty startlingly horrifying. Not sure I would hold Python up as an exemplar.
jibalt 10 hours ago [-]
How many C++ implementations are there?
How many Python, D, Zig, Odin, etc. implementations are there?
And considering the number of users, only Python has an even measurable fraction of the number of C++ users.
StilesCrisis 17 hours ago [-]
It's early days for WebGPU. Safari only enabled it in version 26, so for most of the web it's only a year old. Give it time.
Arainach 17 hours ago [-]
BDFL neither scales nor perseveres. People have multiple things competing for their time and attention. They get old. They probably want to retire eventually. Eventually they die. If you want something to last more than a decade or two, BDFL is a poor choice.
timschmidt 17 hours ago [-]
Linus stopped scaling sometime in the late 90s - 00s. That's when lieutenants took over more authority, and a more or less informal line of succession formed. BDFLs can promote their own replacements from trusted collaborators who share the vision.
zahlman 16 hours ago [-]
For that matter, Python gave up on BDFL something like 8 years ago.
rudedogg 17 hours ago [-]
> BDFL neither scales nor perseveres. People have multiple things competing for their time and attention. They get old. They probably want to retire eventually. Eventually they die. If you want something to last more than a decade or two, BDFL is a poor choice.
Well I mean you're just wrong, you can look at any of those languages (or https://en.wikipedia.org/wiki/Benevolent_dictator_for_life). Python is over 30 years old and it's going fine. You don't see people ragging on Guido everywhere. But everyone pokes fun at the C++ committee and the wacky shit they cook up.
Design by committee just sucks. Coordinating and working with people is expensive, and a drag. If you have to, you have to, but for many projects you don't and shouldn't. An individual's design is always going to be more cohesive, and we can see it clearly looking at PL history IMO.
Jtsummers 17 hours ago [-]
> Python is over 30 years old and it's going fine. You don't see people ragging on Guido everywhere.
Guido stepped down from that role 8 years ago. It now has a 5-member steering council along with the core developers as the primary maintainers and decision makers.
That said, I'd agree with GP that design by committee does suck and I'm not impressed with several of the decisions the SC has made since.
16 hours ago [-]
kllrnohj 17 hours ago [-]
> Or you do the BDFL model like Python, D, Zig, Odin, etc.
Python doesn't have a BDFL[1] and the others are toys.
1: Guido stepped down in 2018 and stopped involvement entirely in 2020 after an extended conflict with the community at large over PEP 572
rudedogg 17 hours ago [-]
> Python doesn't have a BDFL
Thanks, I relinquish that point and accept it as a success story for BDFL succession instead.
wang_li 18 hours ago [-]
It’s pretentious to say they own the language. They own their standard. Yet every major compiler implements something else and are all called c++ compilers.
Arainach 17 hours ago [-]
The standard is the language. Again, you're arguing semantics.
timschmidt 17 hours ago [-]
The standard is a completely conceptual description of an idealized version of the language.
The implementations are the language.
One learns this when their standards-compliant code fails to compile.
account42 8 hours ago [-]
Then it's not a language anyone uses.
bluGill 16 hours ago [-]
The major compilers are certainly behind the latest standard as far as what they implement and if you're trying to run the latest and greatest you will find things that don't work.
You will find, though, that every major compiler considers those features that don't work either. Don't work because of bugs or they're not implemented yet. But either way, it's something they plan to implement.
Your objection reads like 1995. Of course, the C++ standard didn't exist until 1998, which is my point. Compilers have generally considered it a bug to not have all features implemented - the exception that proves the rule is export, which was removed from C++11 because all compilers agreed they weren't going to implement it.
rerdavies 13 hours ago [-]
And now (and then) all major compilers have their own compiler-specific versions of export. Go figure.
jibalt 10 hours ago [-]
> pretentious and misunderstands
The most self-descriptive comment I've seen in a long time.
deleted_flagged 18 hours ago [-]
[flagged]
eldenring 18 hours ago [-]
imagine you run into ub in your C program. Suddenly every single loc of your project, including dependencies, are in scope.
With Rust, only the unsafe blocks are in scope. The point of Rust is not to eliminate unsafe code, but to make it not scale with the size of your program. There is no good reason for those to be coupled.
bobthegoggles 17 hours ago [-]
I tend to wonder, in an alternate reality, where the buck stopped at C for systems languages, would we be better off because more people would use it and know how to fix memory related issues?
We’ve sent rockets into space running C/C++ and assembly. And that was long before C++11 rolled around.
I’m wondering because: man Rust is an ugly language. C is not perfect either, but it’s still pretty close to what it was FIFTY YEARS AGO.
Fast forward to now, and all we’ve come to is Rust? I just wonder why don’t we just keep using C, C#, and Java? I mean the former two are memory safe, and they can do “unsafe” just like Rust.
Another thing: why do we write pseudocode and not design languages to look like pseudocode? With Rust and modern C++ compile times you’d think the machine is parsing prose and turning it into assembly…
katdork 17 hours ago [-]
over-obsession with the language's aesthetics ignore that the type system / borrow checker / ... are good and legitimately assist with development and did so even before the widespread use of LLMs.
many of those who ended up as Rust developers came from C and C++, seeing improvement from what they were using.
languages have been designed more and more to allow for higher level behaviours, in Rust's case, although not pursuing psuedocode, generally allows for very high level abstractions. regardless the computer still has to run things, languages are typically deterministic in their handling and psuedocode leaves much undetermined, unfully specified.
bobthegoggles 16 hours ago [-]
So then why not use C# or even F# for language abstractions? Or clojure on JVM?
Just playing devils advocate it seems higher level behaviours don’t belong in a low level language.
katdork 57 minutes ago [-]
one of the best parts of building up lower level pieces of work/abstraction is that you can eventually produce a higher level interface to them that makes working with them entail a lot less overhead to you or someone else. (that said, in any language it's hard to make said interfaces not have holes or be painful somewhat to some subset of their consumers!)
in some respects, rust is not all the way there for high-level work, but great strides have been made to make it pretty darn close.
having a single language to do your work in, although i personally don't subscribe to it (and am a fan of clojure, guile, C, C++, Rust, Zig, ... all without this feeling to be a contradiction for me) minimizes cognitive overhead and also reduces the quantity of interfaces you need to concern yourself with to manage interoperability. the borrow checker and type system to a seasoned rust user are not a bother regardless of the work they're doing, so it's not like that presents a unique problem.
avoiding garbage collection, avoiding the CLR, whatever overhead comes with it and the joys of .NET Core or overheads of clojure + jvm compiles can certainly be worth it (a clojure project of mine spent 33% of its runtime on java+clojure compilation!)
the lower level work being performant means that your well-designed interfaces can also run well.
aw1621107 16 hours ago [-]
> I tend to wonder, in an alternate reality, where the buck stopped at C for systems languages, would we be better off because more people would use it and know how to fix memory related issues?
I think that period has arguably already come and gone. C and C++ have been the most popular systems languages for decades. I think it's clear that mere popularity is not sufficient to produce memory-safe software with those languages. If anything, those languages are experiencing somewhat of a renaissance these days and it's these more recent developments that end up producing improvements with regard to memory safety.
> I just wonder why don’t we just keep using C, C#, and Java? I mean the former two are memory safe, and they can do “unsafe” just like Rust.
Bit of a nitpick, but I think you meant "latter" instead of "former".
That aside, there's more to picking a language to use than just memory safety and the ability to perform "unsafe" operations. Take your pick from more technical reasons (zero-overhead FFI to C, low-level control over data structures/operations/runtime, etc.) and more "soft" reasons (language affordances/features, ecosystem, etc.).
> Another thing: why do we write pseudocode and not design languages to look like pseudocode?
Perhaps COBOL might be what you're looking for? :P
As with many things, language design is full of tradeoffs, particularly when you want to produce something that is not too unfamiliar to a certain audience. IIRC another factor is that languages that want to work well for "experts" will tend to favor different points on the design spectrum. Consider APL-family languages - those are completely incomprehensible to anyone not familiar with them, but that same terseness is highly valued by proficient practitioners and is something pseudocode-like (or even "regular" code-like!) could never replicate.
bobthegoggles 16 hours ago [-]
All fair points, and yeah I meant latter. :)
It’s just interesting that ALL of these languages have a C compatible interface built into the language. That’s an interesting fact and says something about C that no other language can really claim. Nor will any other language claim that any time soon.
I’m not looking for anything in particular. It’s just that I’ve seen and used a lot of languages over the years, and I’m not wholly sold on the “memory safety” of Rust when something like Python can just put the performance sensitive parts in C and have safety for everything else.
Most languages are memory safe.
aw1621107 15 hours ago [-]
> and I’m not wholly sold on the “memory safety” of Rust when something like Python can just put the performance sensitive parts in C and have safety for everything else.
> Most languages are memory safe.
As I said, there's more to Rust than just memory safety. If memory safety were the only thing Rust offered then I think it wouldn't have garnered nearly as much attention as it has. It's memory safety on top of everything else that makes it as interesting as it is.
>
> Unimplemented — GCC 16.1 (released 2026-04-30) ships it only as experimental
It will always be experimental before it is standardized, because before standardization the specification could change which means if it was not experimental, GCC had to maintain a standard-incompatible implementation.
Expecting a non-experimental implementation as a requirement for standardization is an impossible goalpost.
Searching for contract_assert on GitHub, I only found TrenchBroom projects using it; apart from a few projects hiding contract_assert behind a preprocessor macro, which seems like an entirely unintended way to go about contracts.
I also tried to search for "pre(", but only found false positives.
In contrast, there are hundreds of files across repositories on GitHub using std::meta.
Maybe, so; we should all just use Rust in the holy and consecrated name of memory safery. Oh, whoops, Rust is not memory safe, and usage of unsafe is widespread in some algorithmic work, the kind of already-difficult work where the extra difficulty of unsafe worsens matters.
https://materialize.com/blog/rust-concurrency-bug-unbounded-...
https://github.com/rust-lang/rust/blob/main/library/core/src...
What does that have to do with C++? Enormous pressure was put on C++ to change, in the name of holy memory safety, and C++ contracts was claimed by some to directly address memory safety. And the pressure came in large part from the Rust Foundation and related parties and individuals, such as Steve Klabnik. Funnily enough, Steve Klabnik is very active on C++ forums, and he has "strong forum-voting powers" both here and elsewhere.
That push for holy memory safety was not done in the interest of improving C++ or improving the state of programming. If they, Rust Foundation and company, had had an interest in improving C++, they would instead have tried to add the actually good parts of Rust to C++, namely tagged unions and pattern matching.
Their focus is also in many ways not beneficial to neither Rust nor programming generally, since a lot of energy is spent hiding the actual issues of Rust, thus diverting resources and attention away that could have been spent improving and fixing Rust.
Perhaps Mozilla was right in paying mental-medication-taking Steve Klabnik the least for his community-focused work, after all, his primary focus was not engineering, and he might harbour a burning hatred and envy for actually talented engineers. Or maybe Mozilla should have fired him while they had the chance long ago.
I remain unconvinced as why this is a necessary feature over the already existing `assert` statements.
So more about the hype in itself and less about HN specifically.
I guess I could have added that part as well.
So yeah, I guess I got a bad reply there, sorry about that.
This line is where I realised it's Claude. Also note the emdashes.
That LLMs use them all the time is also a good indicator that there are alot to be found in the training material.
[1] https://www.merriam-webster.com/grammar/how-to-use-and-under...
Bjarne’s opposition to contracts might have tipped the scale but there is definitely growing weariness (and wariness) about large half-baked features that are left as exercises to the implementors (looking at you modules).
Ignoring that historical context when analysing this vote seems like a mistake.
It also lists 6 possible paths forward for C++26 with pros and cons. I think they are roughly:
A. Skip an official C++26 standard but roll these features into C++29.
B. Remove contracts from C++26 and pass it.
C. Say "please" and vote again.
D. Tweak contracts regarding virtual functions and vote again.
E. Pass C++26 as many different countries' national standards rather than an international standard.
F. Do E and also consider leaving ISO and moving to ANSI/INCITS instead.
If, on the other hand, you mean only that, regardless of the status of a contract, if the compiler can detect that it would be violated, it must have failed to compile, I guess that would be all for that. On the other hand, the state of theorem provers that are able to prove things will and won't work is ... evolving. There will a lot of people be frustrated when they upgrade their compiler to a minor point release and suddenly a lot of code fails to compile because it always was broken but likely in an obscure situation that never happens in the real world.
I'm not sure I can express it better than the proposal to add the corresponding feature [0]:
> This extension addresses the Romanian National Body's (NB) concern by enabling the writing of an individual contract assertion that guarantees the program execution will not continue past the contract assertion if it is violated, regardless of the semantics of other contract assertions. This addition to the C++26 Contracts facility allows reliable use of enforced contract assertions in large codebases with mixed contract semantics and also in hardened libraries.
> Is it worth the trade-offs?
Apparently some people/NBs feel quite strongly that it is.
> There's a reason why most code turns assert off in production and only does it in debug builds.
There's also a reason some codebases define asserts that aren't turned off in production in addition to debug-only asserts. The proposal lists multiple under Section 3.1 Existing Practice.
> and so if the code is trusted to work, you wouldn't want to check that it's working correctly.
Right, but sometimes you might think the consequences of such blind trust being misplaced are worse than the performance hit.
Static detection of impossible-to-satisfy contract conditions would be interesting, but as you say the technology is probably not ready for the kind of widespread use that inclusion in C++ would entail.
[0]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p39...
And now I'm even more confused. Why is this so critical that we can't say we're going to put it in another next version of the standard? Compile is regularly see things in the future version of standards and them implement early. I'm not disagreeing with the paper. I'm disagreeing that this is so critical it needs to abort the whole process.
This feature was first proposed in 2004. In 2018, they were added to the draft of the standard, and then removed in 2019. So that already has been happening, for over a decade.
Part of the reason this is coming to a head is that it's already been a long time. Another reason is that some see contracts as fitting into the safety story for C++. Part of it is because, well, standards are done by the people that show up, and the people who show up care about this.
> I'm disagreeing that this is so critical it needs to abort the whole process.
It's a byproduct of how the process works. There are a series of votes, and they're not done by the same people. Some people voted yes to put them in, and then the vote after involved people voting no, they don't think they're good enough to put in. It is not so much that "this is so critical that it needs to abort the whole process," so much as it is "the final vote is the time when those people get to express their support or dissent." One of the proposals in the paper is that they could remove this feature, and then the rest would likely move forward. It will only hold up the entire thing if the people who are pro this feature landing decide that it's worth holding everything else up for.
More and more I'm on the side of those who are point at the 'no' votes as babies who can't work together. This is not a new thing and your preferred action isn't the best compromise, grow up. I know that is insulting, but it seems well deserved
I have a feeling that the paper isn't even a good way to solve their problem, but I can't quite figure out what would be better.
The only red-string-on-a-cork-board I can connect is between guaranteed enforcement and the design decision that "contract assertions must not be used for error handling and input validation". The latter would seem to rule out guaranteed enforcement now and in the future and EWG apparently voted against P3911 back in January [0], so perhaps they think that they won't ever see guaranteed enforcement if contracts is left in the standard as-is.
That's all quite speculative, though, so take that with an appropriately-sized grain of salt/
[0]: https://github.com/cplusplus/papers/issues/2536#:~:text=Dire...
But these proposed contracts... I just don't really see much benefit it offers over just explicitly writing your own assertions.
I suppose you can see the requirements in the declarations, but I would wager that fancy modern C++ declarations quickly become so long and verbose that you'd get quickly fatigued from reading them. Perhaps in the LLM era they are more useful?
It seems like part of the concern is that the feature needs to be shipped right the first time because it'll live forever. Perhaps allowing features to be deprecated and then removed could help?
But idk, I haven't written anything that lasted 36 years, so maybe the current approach is for the best!
C++ definitely has complexity, but I'm surprised by the two examples specifically chosen. Which pointer? C++ only has 2: unique_ptr and shared_ptr (or 2.5 if you want to include weak_ptr but that necessarily means you already chose strong_ptr first). While this might be a complicated choice if you're just comparing to Python, but it shouldn't be if you're familiar with Rust since Rust has you make the same choice.
And then "how should I iterate" is similarly the same as any other language? Either a for or a for-each loop?
There's definitely baggage from 38 years of lessons learned, to be sure, just those examples are odd choices
https://en.cppreference.com/cpp/language/pointer
When I started C++ nearly 15 years ago this was already a huge problem. I bought some books and looked up online references and after a while I discovered that both were already out of date.
C++ is a chimera. And it hasn't improved since.
Other languages are far more stable, conceptually. New features rarely undermine or reinvent the older ones.
C++ is unique in the way it keeps modifying its own core. There is no formal deprecation or EOL process, so the language is more like an archaeological dig than a living standard.
Yes there is or we'd have been talking about std::auto_ptr as well.
> New features rarely undermine or reinvent the older ones.
Many languages have mistakes they've later tried to sweep under the rug. JavaScript arrow functions trying to convince everyone that bind(this) wasn't ever a thing, for example.
C++, for whatever reason, is consistently the only language where people are determined to always dig up the skeletons and pretend they are at all still relevant. It's not unique in having skeletons. It's not unique in having language spec mistakes that can't realistically be changed, just ammended with a newer, better alternative.
But like the saying goes, there are only two kinds of languages: the ones people complain about and the ones nobody uses
for (ignoring do and while) and foreach loops, std::for_each, ranges for_each at the very least
Java: for, for-each, do-while with iterator, list.forEach(..), list.stream().forEach(..), etc...
When the language got operator overloading there was the question of how to convert the arguments from the operator itself to its implementation. You wanted to write a+b, not &a+&b but most versions of operator+ were going to want const pointers for efficiency. One option was to make the & implicit, another was to introduce a type of argument that didn't need & but acted like a pointer. So references were born.
I ignore people who advise to use references when something can't be null. A null reference is UB just like a null pointer, it just shifts where the UB is, but the compiler is likely to produce the same code either way and the program is just as likely to crash. Instead, I use pointers to make it obvious that something is a pointer, and references when it should be invisible, just like with operator overloading.
Didn't they say they use references when the pointer/reference should be invisible?
My understanding was that const references don't provide that much in the way of optimization opportunities (if any?) due to aliasing and the existence of const_cast.
And even without such a change, such a restriction is pretty easily worked around without a const reference with something like T&& temp = get_daily_prices(); sum(temp);. I don't think that'll result in different codegen than either passing a temporary to a const ref or allowing binding a temporary to a non-const ref.
EDIT: by "exactly how you fear it would", it just did a dereference and return. It didn't check for null, didn't throw, and couldn't otherwise signal a failure.
Do you know C? Everything that works in C works in C++, modulo a few minor syntactic changes (void* doesn't implicitly convert). You can get acquainted to C++ features on an as-needed basis. Other people will surely disagree with me on this.
With pointer types in particular, I'd say use C-style pointers long enough to know how frustrating they are but also how they work. Then you'll know what unique_ptr and shared_ptr are doing to help you. (And those are the only two you need 99% if the time. weak_ptr is a spin-off of shared_ptr that you'll know if you need it. observer_ptr is just stupid ivory-tower stuff.)
weak_ptr is like shared_ptr but doesn't add to the count. When the last shared_ptr is destroyed it destroys the object even if there are still weak_ptrs. Any weak_ptrs pointing to that object become null. I won't dive into how that's actually implemented. Obviously it costs some CPU cycles to make that happen, so you don't see shared_ptr or weak_ptr a lot in code that's written with a performance mindset. Although you're still getting 90% of the performance benefit by writing C++ instead of JS even if it's "inefficient" C++.
I agree with GP's point and add, if this isn't something you need to do, then don't even think about it. C++ is like a toolbox with a bunch of tools. I don't study all the tools before building a table, I look up how to build a table, and then see if the tools are in my toolbox. Studying the triangle screwdriver would be a waste of time and only confuse me more, unless I'm trying to drive triangle screws. Only when I need to drive a triangle screw then I can look for the triangle screwdriver.
https://docs.python.org/3/library/weakref.html
Anyone that thinks Python is "simple", to come back to some of the suggestions on how it is easier than C++, they really should learn the language reference, standard library, and CPython FFI manuals.
Python is more "simple" in the sense that
- it is more forgiving with respect to badly written code,
- it has collected less historical baggage than C++.
Otherwise I agree.
Yeah, we all know how cleaning up Python has worked out, and unfortunately a few ecosystems failed to learn from it as well, e.g. Java 8 => 9, .NET Framework => Core.
C++ does have many ways to do anything. Most of that is historical, or due to features and library facilities with overlapping capabilities, or inherent to multi-paradigm programming languages.
Every C++ project is written in its own language. Its own "house flavor." This is true of all languages, but is particularly stark for a language as old, complicated, and powerful as C++.
> pre-LLM, so maybe it's better now?
I came back to the toy tool some time later and used GLM 4.x to implement it further. I had a good experience with it and I understood the code it generated. From my experience, in general, LLM is a good mentor, if you are willing to ingest the content step by step. For me, it is no different from when I used StackOverflow (and other forums) to try and ask how a thing is done.
And was it the language itself or the libraries?
You can of course use Python. But we are talking about languages with different applications. You want fast development hand have no expectations on speed? Use Python! You want to control your computer to get maximum performance with a safe type system? Use C++!
Since you are already talking about pointers: In Python you are not even given the chance to do all the stuff you can do in C++. You have to rely on garbage collection (and "del"). That is an entirely different thing than C++ where you exactly control how long your objects should live.
For the pointers (order I would suggest): 1) No pointers, use references whenever possible 2) Use std::unique_ptr 3) Use std::shared_ptr
You can also try to use shared_ptr all the time if it makes your transition from Python more easy. It is not optimal, but it may get you started.
And do not start wrapping your head around rvalue references right from the beginning. This is a very special topic, which you can ignore as a beginner.
Which also has plenty of way to do the same thing.
People often mistake the easiness to write Hello World, with the real expressiveness that is available in any given language.
The answer is almost always: no pointer
- it shines for some tasks where Rust isn't capable enough
- it's impossible to get rid of because of all the code so we may as well modernize it
- there's an active community of people who built a career of being C++ experts and have no interest to see the language disappears.
Even in the LLM era, I find it's difficult to code in C++. The language has so many corner cases that LLMs make mistakes. My experience 6 months ago was that the code written by my agent had tons of complex linter warning (exceptions, lambda leaking references, futures whatever... that I just can't avoid because the codebase mixes all of this). Whenever possible, it's probably time to either modernize it or port it to Rust, component by component, until the C++ part is small or inexistant.
Modern best practice for C++ is to crank the warnings to maximum, and to treat warnings as errors. You absolutely should treat linter-like warnings as an error, because they invariably are. So you know.
what should be conclude from this? this is like saying you tried to become a professional trapeze artist for a couple of days. C++ is complex and deep. what did you seriously hope to accomplish in a "few weeks"?
i started writing C++ professionally 4 years ago, i.e., i write it every single day at $JOB. there are still large parts of the language i'm not familiar with.
Yes, that's the point. Much of this complexity would not be necessary to achieve the same things, given the ability to redesign from scratch.
It's basically everyone learning from everyone else on what works and what doesn't work.
C++ 11 wants to model two non-trivial orderings, Acquire-Release and Consume-Release, but only Acquire-Release is actually usable. So yes, C and Rust both also choose to offer Acquire-Release ordering like C++ but it's also clear that the universe of possibilities is actually smaller than WG21 realised when C++ 11 was developed.
If on your first random stab you guess 65537 is prime, you're correct and you might foolishly assume all those Fermat Numbers are prime and then try say, 4294967297. Nope, that's divisible by 641 for some reason. There are only Five of these Fermat Primes so far as we know, they weren't common after all.
I sometimes wonder how difficult it would be for a compiler that was designed from the outset to implement Consume correctly.
I've sketched what I think an ideal "language of today" would look like, and one of the core tenets is making concurrent code explicit and part of the design surface.
You might imagine a webserver with main code like:
Or iterating over "num_cpus" and doing the same thing, with hashing based on CPU number for shared-memory resources.The vast, vast majority of software, and software developers, simply do not care about core affinity, NUMA, noisy neighbors, etc.
Even on systems or situations where this matters (massive number of cores and memory, multiple sockets, thousands of threads, etc.) the juice is rarely worth the squeeze.
Doubly so when you end up being I/O bound anyways.
Nearly every software developers wants their software to work across multiple deployment targets. Maybe you just target x86-64, and you don't care about the number of CPUs because you'll be upgrading your servers every couple of years.
No one wants to deal with difficult-to-reproduce issues related to scheduling in niche configurations. It's much more efficient for runtime or compiler engineers to solve these problems for us, leveraging the vast amount of resources of corporations to develop and test these features. Then you have a place your code can live happily ignorant of its runtime constraints.
And that, my friend, is the beauty of our industry.
The effects can be subtle and lurk for years until a seemingly unrelated change exposes them. It starts with optimizations like instead of spawning a thread, you use a thread pool, possibly abstracted as some kind of executor service. Other code might use different thread pools to isolate them because each pool has its own limits on the number of threads. Some might grow but usually they won't.
Until one day you end up with thread starvation and a deadlock through a series of benign seeming optimizations. There are threads around but not in the right pools and the entire thing grinds to a halt.
Cooperative async/await on a single thread is the ideal solution for most use cases, particularly with complete environment teardown between requests. Yes, this is basically the PHP model.
In my opinion, that's really the best place for it. From what I understand, that's always been FORTRAN's secret sauce.
I've been doing threaded code since Day One (Machine Code), and have gotten it wrong, quite often. There are a million things that can cause concurrent code to actually perform worse than single-thread code.
These days, I usually just let the platform pick the threads, and generally write code that will play along.
Anything else heavily uses concurrency in all kinds of ways.
1. C++ is unsafe. Bjarne keeps giving talks that effectively say "use it perfectly and don't make any mistakes and it's safe". That's not useful anymore. In a world where LLMs can find every mistake to exploit it, all the C++ projects are struggling to keep up and keeping them in C++ is basically guaranteeing there will be more exploits in the future. Yes, not every bug gets solved by switching to a safer language but reducing the attack surface in the new reality is no longer something that can be put off.
2. LLMs can re-write. The previous arguments used to be "there are C++ legacy code bases so C++ will never die". That was a valid argument before an LLM would just rewrite it all. I get people will say they aren't perfect, neither are humans though. Further they get better all the time, and we see their progress. People pointing an LLM at some project and it magically making it work on some other platform etc... It's clear it's happening.
Plus, there are a lot of pros to C++ which aren't so easily waved aside. The breadth and duration of support makes it almost impossible to kill quickly, imo. If a magical LLM bullet shot C++ dead tomorrow, many established orgs and projects would keep it rolling. It also sits in a funny spot where you can get pretty good performance from not-great code. And it is incredibly fun to write! Reading it is... another matter ;).
Edit: I'm sure dumping piles of money into abliterated models can get you quite far. ROI and correctness are the parts I'm still sus about, however I hope to be proved wrong.
I'm not ashamed to admit that I occasionally ask my LLM to find and fix all the bugs in a file. And not ashamed to admit that it often does. Most usually algorithmic problems, not memory problems, fwiw, because I use modern C++.
It will probably take a lot longer to die than I expect, though, too many legacy third party libraries are written in C++ and most people don't really like the syntax for the logical alternative (Rust).
It very obviously does not. Stating what you want to be true as "facts" does not make it so but rather discredits the one making the assertion.
And the article also mentions that divergence is a real possibility in situations like this.
Or you do the BDFL model like Python, D, Zig, Odin, etc.
I think it works better. A language that reflects the vision of an individual deeply thinking about the interactions of language features, and being able to say "no" to anyone/everyone has many benefits.
Committees make me think of the Web, C++, Swift, etc., and they have a lot of "odd" decisions that have had a heavy cost. Swift has https://www.swift.org/swift-evolution/, but a lot of ideas with minority support were pushed through by Apple (for SwiftUI mainly), against overwhelming community feedback.
And the Web has had a lot of "duds" when you think of WebGPU, WASM (not saying it's bad, but people clearly want to stop writing TS/JS and they haven't made that a reality yet, at least in a way I'd call "successful"), etc.. Oh and DRM in the browser sucks. I forget the details but I was goofing around with FreeBSD Desktop and couldn't get various things to work due to some browser DRM bullshit. https://en.wikipedia.org/wiki/Widevine if curious.
How many Python, D, Zig, Odin, etc. implementations are there?
And considering the number of users, only Python has an even measurable fraction of the number of C++ users.
Well I mean you're just wrong, you can look at any of those languages (or https://en.wikipedia.org/wiki/Benevolent_dictator_for_life). Python is over 30 years old and it's going fine. You don't see people ragging on Guido everywhere. But everyone pokes fun at the C++ committee and the wacky shit they cook up.
Design by committee just sucks. Coordinating and working with people is expensive, and a drag. If you have to, you have to, but for many projects you don't and shouldn't. An individual's design is always going to be more cohesive, and we can see it clearly looking at PL history IMO.
Guido stepped down from that role 8 years ago. It now has a 5-member steering council along with the core developers as the primary maintainers and decision makers.
That said, I'd agree with GP that design by committee does suck and I'm not impressed with several of the decisions the SC has made since.
Python doesn't have a BDFL[1] and the others are toys.
1: Guido stepped down in 2018 and stopped involvement entirely in 2020 after an extended conflict with the community at large over PEP 572
Thanks, I relinquish that point and accept it as a success story for BDFL succession instead.
The implementations are the language.
One learns this when their standards-compliant code fails to compile.
You will find, though, that every major compiler considers those features that don't work either. Don't work because of bugs or they're not implemented yet. But either way, it's something they plan to implement.
Your objection reads like 1995. Of course, the C++ standard didn't exist until 1998, which is my point. Compilers have generally considered it a bug to not have all features implemented - the exception that proves the rule is export, which was removed from C++11 because all compilers agreed they weren't going to implement it.
The most self-descriptive comment I've seen in a long time.
With Rust, only the unsafe blocks are in scope. The point of Rust is not to eliminate unsafe code, but to make it not scale with the size of your program. There is no good reason for those to be coupled.
We’ve sent rockets into space running C/C++ and assembly. And that was long before C++11 rolled around.
I’m wondering because: man Rust is an ugly language. C is not perfect either, but it’s still pretty close to what it was FIFTY YEARS AGO.
Fast forward to now, and all we’ve come to is Rust? I just wonder why don’t we just keep using C, C#, and Java? I mean the former two are memory safe, and they can do “unsafe” just like Rust.
Another thing: why do we write pseudocode and not design languages to look like pseudocode? With Rust and modern C++ compile times you’d think the machine is parsing prose and turning it into assembly…
many of those who ended up as Rust developers came from C and C++, seeing improvement from what they were using.
languages have been designed more and more to allow for higher level behaviours, in Rust's case, although not pursuing psuedocode, generally allows for very high level abstractions. regardless the computer still has to run things, languages are typically deterministic in their handling and psuedocode leaves much undetermined, unfully specified.
Just playing devils advocate it seems higher level behaviours don’t belong in a low level language.
in some respects, rust is not all the way there for high-level work, but great strides have been made to make it pretty darn close.
a talk from dioxus on the state of high-level rust: https://www.youtube.com/watch?v=Kl90J5RmPxY
having a single language to do your work in, although i personally don't subscribe to it (and am a fan of clojure, guile, C, C++, Rust, Zig, ... all without this feeling to be a contradiction for me) minimizes cognitive overhead and also reduces the quantity of interfaces you need to concern yourself with to manage interoperability. the borrow checker and type system to a seasoned rust user are not a bother regardless of the work they're doing, so it's not like that presents a unique problem.
avoiding garbage collection, avoiding the CLR, whatever overhead comes with it and the joys of .NET Core or overheads of clojure + jvm compiles can certainly be worth it (a clojure project of mine spent 33% of its runtime on java+clojure compilation!)
the lower level work being performant means that your well-designed interfaces can also run well.
I think that period has arguably already come and gone. C and C++ have been the most popular systems languages for decades. I think it's clear that mere popularity is not sufficient to produce memory-safe software with those languages. If anything, those languages are experiencing somewhat of a renaissance these days and it's these more recent developments that end up producing improvements with regard to memory safety.
> I just wonder why don’t we just keep using C, C#, and Java? I mean the former two are memory safe, and they can do “unsafe” just like Rust.
Bit of a nitpick, but I think you meant "latter" instead of "former".
That aside, there's more to picking a language to use than just memory safety and the ability to perform "unsafe" operations. Take your pick from more technical reasons (zero-overhead FFI to C, low-level control over data structures/operations/runtime, etc.) and more "soft" reasons (language affordances/features, ecosystem, etc.).
> Another thing: why do we write pseudocode and not design languages to look like pseudocode?
Perhaps COBOL might be what you're looking for? :P
As with many things, language design is full of tradeoffs, particularly when you want to produce something that is not too unfamiliar to a certain audience. IIRC another factor is that languages that want to work well for "experts" will tend to favor different points on the design spectrum. Consider APL-family languages - those are completely incomprehensible to anyone not familiar with them, but that same terseness is highly valued by proficient practitioners and is something pseudocode-like (or even "regular" code-like!) could never replicate.
It’s just interesting that ALL of these languages have a C compatible interface built into the language. That’s an interesting fact and says something about C that no other language can really claim. Nor will any other language claim that any time soon.
I’m not looking for anything in particular. It’s just that I’ve seen and used a lot of languages over the years, and I’m not wholly sold on the “memory safety” of Rust when something like Python can just put the performance sensitive parts in C and have safety for everything else.
Most languages are memory safe.
> Most languages are memory safe.
As I said, there's more to Rust than just memory safety. If memory safety were the only thing Rust offered then I think it wouldn't have garnered nearly as much attention as it has. It's memory safety on top of everything else that makes it as interesting as it is.