256 comments

[ 0.30 ms ] story [ 12.3 ms ] thread
Maybe this time could be used to consider memory safety much more seriously.
Memory safety was solved in 1959 with the invention of lisp
The issue that caused this to be voted down is often seen as a memory safety solution (not something I personally 100% agree with, but thats a broad view). And the rest of this release includes other memory safety work. And it was voted down and delayed for apparent political reasons (again not a view I agree with).

So most people will read your view as hypocritical/misinformed.

It could also be read as a straight up attack. Basically, a way of saying “why not follow Rust“ without having to say the word Rust.

I think it was a fair question. As someone who doesn’t follow C++ I really don’t know what else was in the proposal. It’s nice to hear there is memory safety stuff.

The memory-safety-relevant parts of the proposal could be salvaged without keeping contracts more broadly, by saying that the relevant behaviors (like indexing past the end of a std::vector) cause program termination in hardened builds. I'm sure it's more complicated than this but I don't think much more.

More generally, the C++ committee has had a really hard time agreeing on memory-safety stuff because there are a lot of different constituencies with completely different priorities (especially whether they're using it for greenfield vs. legacy vs. something in between), and the incentive is to make proposals sound good to everyone at the expense of actually being coherent.

Maybe my reading comprehension has just nosedived but I could not find where this article discusses what the heck Contracts refers to?
- since you are a part of the voting group, i have a doubt

- let us say tomorrow everyone were to consider removing all unsigned variables across c++

- what is the impact in terms of compatibility for all the old c++ applications which i believe would be millions of them if not billions?

- the reason i ask is they say do not unsigned anything as much as you can because overflowing the bottom below 0 is easy

- has there ever been any consideration to get rid of unsigned xyz in c++?

you know downvoting without explaining why is part of herd mentality. i expected better on HN. dont you wanna give some reasons as to why you find this offensive?
> - let us say tomorrow everyone were to consider removing all unsigned variables across c++

We would have to at the same time consider removing all bit operations (shifts, bit_and, bit_or, complement, xor, ...) as they are generally unsafe for signed integers.

That would probably kill a lot of low-level optimisations you were never actively aware of (some tagged versions of SSO, or pointer tagging in general, ...) but relied on for performance.

So, without thinking of further consequences, I think C++ would be worse of with that proposed change.

I feel like this is a bellwether event for society at large. Growing impasses between more and more segments of society. Diminishing trust leading to the inability to reach consensus. Maybe it’s just me though.
Perhaps it is, in this case it would be between money and everyone else specifically. Contracts is a pet project of Microsoft and the heavy money parts of the committee. They've basically shouted down the dissenters, hence the effectively unprecedented action of the rubberstamp portion of the process saying they dont think consensus was reached in a kosher way.
I get why some folks would like to see contracts in the language, but C++ is also buckling due to the shear complexity that's getting tacked on to it. I'd rather see more proposals such as C++26's "erroneous behavior" that attempts to reign in the language's shortcomings.
Agree. There's an argument that Contracts reduces the complexity of using the language because it offers a more readable alternative to template metaprogramming (also, it has better error messages). But the argument really falls apart when you review WG21's track record for other features.

Like for example, Coroutines were billed as an easier way to write concurrent code, but personally I think it completely failed and ended up being hopelessly complex and confusing. Modules are the same - superficially they make things simpler, but when people actually go to adopt it, the details are so complex that nobody bothers.

I think you're confusing it with Concepts. Contracts are basically just asserts, nothing to do with templates.
> There's an argument that Contracts reduces the complexity of using the language because it offers a more readable alternative to template metaprogramming

Like most people in this thread, you should really read up on contracts before commenting. The contracts proposal is for runtime assertions, and their problem is that they are poorly specified and fundamentally broken. Their proponents haven't been addressing any of their concerns and tried to push a half baked version of them down everyone's throats, which was why they failed to pass.

Some do bother, e.g. Microsoft Office uses modules, there is a talk on it.
Personally I'd like to see C++ chill out on new features and maybe sort out the shitshow that is char8_t and std::filesystem.
Maybe a slightly faster std::regex or whatever it's called; apparently it's horrendously slow for no benefit.
The primary reason this hasn't happened is that it'd break C++'s de facto stable ABI (even though officially there's no such thing). For a lot more context, see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p20... and https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p18....

Spoiler alert: The option described as "the sort of leadership failing that I pray we can avoid" is what ended up happening.

Who cares about the ABI when the current ABI has a bunch of bad issues with it. For any backwards compatibility thing there is always AI that can rewrite old code.
The compiler vendors care. It is also the reason why C++ never actually had a GC, even if the standard had it specified (and removed it with C++23).
ABI isn't just what rewriting code. Even if you rewrite the code, you still have to test it, certify it, and so on. Because C++ has an ABI, I mix code that is already built with new code and only recertify my new code.

It is a huge pain, and quite honestly, most of the reasons I have to maintain ABI are political and thus not up for a technical discussion, but I still have to do it.

You can make linking against different abi not allowed. And all the stuff you are complaining about can be handled in <24h by an AI agent.
I'm pretty sure that it is too late for C++ to break the "stable ABI" they already have.

It's not too late to introduce an actual stable ABI though. However, it's not too late to do that in Rust either so I don't see the point in a language specific ABI in the future anyway.

As an avid non-C++ programmer, can I suggest doing something about the build/module system? I shouldn't have to learn a separate language (CMake) and figure out the right include files to pull in a library.

I mean, I mainly say this to joke because it's probably unfixable at this point, but whenever I mess with it, I'm struck by how hard/opaque C++ makes this problem compared to most other languages.

[dead]
Sure, but JS has a myriad of choices too and yet we mostly agree on node_modules, package.json and npm (the repo). Big companies or weirdos are free to swap any of those with something else if they want but the little guys have something standardish if they don't want to inflict too much pain upon themselves.
There is no standard build/module system or way of dependency management. Unfortunately, this is because there's no standard compiler with standardized flags so C++ would also have to standardize compiler behaviour too.

Large FAANGs that would be incentivized to change it don't care because they have their own in-house C++ build systems like bazel (Google) or buck2 (Meta) that are far faster than cmake (distributed compilation and caching) but require huge teams to maintain. Unfortunately, this distributed compilation and caching layer is something that many other languages don't have since their build systems are made for single devs building locally.

Also the dependencies can be added in a myriad of ways. Your build system can download them, your meta-build dependency manager can find them (Conan), your Linux distro can provide them (system libraries), or maybe you just download an object file from a website + some headers and are told to figure it out yourself (many commercial packages like cuda or steam).

It's probably possible to improve things here, but it's likely best done as a separate open source project.
Like most things in C++, everybody who uses it professionally has already solved this in one way or another in a way that works for them.

So this is only a painful problem for people who don't use C++ very much, and whatever centralized, official solution to builds would probably not really get adopted by most C++ shops.

Because of that, even if it were solved, it's likely that it would only solve the problems that people who don't use C++ very much, or who don't invest in build tooling, want fixed. Which is basically what Make was originally.

IMO it's best to think of C++ as a language only. Because of Microsoft/Sun/the web/etc and the desire to win over developers' business, a lot of newer languages are designed to be batteries-included with official first party tools that are supposed to be the canonical way to solve that particular class of problems. Those languages are essentially products or brands that are part of their benefactors' grand designs for specific business or career outcomes.

C++ by contrast has multiple competing implementations for basically anything you can think of, and isn't someone's "business" the way most other languages are, so there's no reason to make the out-of-the-box DX better or standardize the tooling. Nobody has any reason to want you to write C++ instead of something else.

As a C++ programmer. No, you cannot!

C++ is used for large, very, very, very, very complex problems. Language-specific build systems always like to assume all the world is their language. But not all my world is C++, just 99% and that last 1% is all kinds of weird, screwy things that require a very complex build system. CMake is up to the task, in part because CMake is used for building more than C++ and so they've thought a little bit about the issues I have.

Anyone who says CMake and C++ are complex languages is utterly completely wrong. Sure, by comparison to something better designed, they're a little more complex, but we're only talking a little bit. Meanwhile, I have tens of millions of lines of code to deal with. My real complexity isn't the language, it's my code and that is far greater than all these little complaints people have about the language complexity.

The lack of a universally accepted "good" build/module system like npm, mvn, cargo, etc... has the side effect of limiting the tendency of relying on way too many dependencies, and also limits supply chain attacks.

I mean, it is a real problem, it is making life hard on developers for no good reason, but sometimes, artificial friction can work against some anti-patterns. Similar in spirit to "chaos engineering".

I like how this post got upvoted by people who share my frustration and then downvoted by fans trying to cope for a build/packaging experience from the last century.
No. The problem isn’t that std::regex is slow and badly designed. It’s that std::regex exists at all.

C++ is unique in that it defines a spec for STL but not implementation. The result is something that is both overspecified and underspecified.

Including batteries is fine. Including a spec for what the batteries should look like is such a profoundly bad idea that no other major language does it.

I'm confused about what exactly you're arguing for. Is the idea that the standard library should be minimal and then each compiler should ship its own nonstandard "batteries" library?
I think the language committee should provide a spec where required (OS filesystem, mutex, etc). And when it is not required they should simply provide a plain bog standard library.

There is absolutely no reason for std::deque to be a specification. The committee should either ship a committee library for std::deque or they should leave it to the community. They can provide a battery or they can not. Providing a spec for a battery that is both over and under specified is the absolute worst possible choice.

Do you also think the committee should ship a compiler? If not, what's the difference?
Compilers are complex, platform specific and the architectures behind them can be wildly different. Maintaining a reference compiler would be a lot of work for no real benefit.

The standard library on the other hand is a library. It's almost always implemented as plain C++ without much platform specific code. ISO could take an existing free licensed implementation and declare it as the standard. Of course anyone is free to make their own competing one, it just has to always match the official library's behavior.

Writing a spec instead of code is just creating duplicate work and compatibility issues any time the spec is unclear.

The difference is that I can trivially write a std::deque container that runs under any compiler that implements the C++ spec.

Why on earth would I want a different implementation of std::deque on each platform I use because the compiler team needed to provide one? It’s madness!

The standard library would just be C++ code that a compiler turns into machine code.

I remember a language where the core language types, including primitives and a bunch of keywords, were actually defined in the standard library and the compiler just special cased support for the types in the standard library for optimization purposes.

Your loaded question feels very silly from that perspective.

I think this is misunderstanding the problem with std::regex -- the problem isn't so much that it provides a "spec for what the batteries should look like" but rather that it is naturally ABI entangled and so the bad first generation implementations are unfixable given that the committee refused to allow for an ABI break to fix this.

The real problem is the latter: C++ has always had a "you don't pay for what you don't use" as part of its core philosophy but it turns out that doesn't apply if the thing you don't use is ABI stability.

(and, failing an ABI break story, std::regex should have had an implementation that was more PIMPL and less template so it would have fewer ABI issues, possibly followed by a regex2 later that could get more of the compile time bits once implementations were more mature.)

I'm sorry you don't like std::regex. That isn't a problem with C++'s specification practice.

C++'s separation of spec from implementation is clearly functional. There are several major open-source standard library implementations that compete on the basis of performance, ABI stability over versions, quality, etc.

C++'s core ethos is "only pay for what you use". std::regex does this. In my experience, the "problem" with std::regex is that it provides more features by default than most people want, and you pay for using those features. Specifically, std::regex respects the runtime locale. There are good reasons a standard library feature might do this (e.g. it simplifies the interface, it's broadly applicable, etc.), but it's obviously not going to give optimal performance. This is a necessary tradeoff for any standard library.

Locale handling requires dynamic memory allocation, virtual function dispatch, sometimes system calls. Locale handling also prevents some low-level optimizations based on the character encoding. If you need that kind of performance, std::regex probably isn't for you, go grab a non-standard library that suits your needs.

locale is a great example of a concept that is catastrophically bad, provides zero value, and shouldn’t exist at all in the spec.

std::regex is so worthless that no one uses it. My codebase gives CI warnings when it’s used. so it’s not even really a problem. It is indicative of a larger problems.

> C++'s separation of spec from implementation is clearly functional.

Your bar of “clearly functional” is is not a compelling or meaningful bar. What a weird fallacy.

C++11 was pretty great and meaningfully modernized the language. The amount of useful good things in each following release got smaller and smaller. Maybe just one or two useful improvements in C++20. Almost nothing in C++23. And now C++26 has failed to pass. It’s grinding to a halt. The biggest recent features such as concepts and modules have been catastrophic failures.

Those failures aren’t all due to my specific complaint of “battery specs are a bad idea”. But “functional” is the lowest possible bar. And one could argue that as a whole isn’t being met.

Time to cancel the project. C++ acquired sufficient set of features over the years, becoming very PL/I-esque.
As someone who writes high-reliability C++ but is completely outside the standards process, I see the issues with C++ Contracts. It isn’t clear that it solves a problem that anyone has in real codebases, especially after C++20 concepts.

If you were already writing high-reliability C++ then the benefits are difficult to quantify. If you weren’t writing high-reliability C++ then it saves you almost nothing over doing the standard idioms of high-reliability C++ that were already available to you at very marginally more cost. It does standardize expression of it in narrow cases but the payoff seems minimal.

Most of what C++ Contracts delivers is a mashup of what you can already do with constexpr and C++20 Concepts. I like reliability features but this feature, as delivered, looks fairly useless if you already use reliability features. A compelling standard would need to make much deeper guarantees out of the box. And the compiler can already see through most compositions of constexpr and C++20 concepts, which is already very expressive.

C++ Contracts looks a bit like a feature that was designed long before current standard features existed.

The problem is that a bunch of people who didn't care for them did something very extreme by voting against approving C++26.

(Also you don't seem to know what they are.)

> The problem is that a bunch of people who didn't care for them did something very extreme by voting against approving C++26.

The only extreme and tone deaf thing I see in this story is how contracts proponents were faced with multiple papers demonstrating quite clearly and extensively how they were broken in specification and in form, but still tried to ignore all the criticism and force them through a consensus process in spite of being clearly opposed.

How does this make any sense? What was the plan here? To blackmail the C++ community to accept a broken feature under threat of the proposal not passing?

Make it make sense?

What I want to see is the people who tried to force contacts upon the process in spite of all opposition to come forth and explain their rationale. It was highly absurd and even unthinkable to force a broken feature down C++'s throats with bureaucratic chicanery, and then complain that the same bureaucracy has mechanisms to stop it's abuse. I for one would like to hear an explanation.

    > high-reliability
I never heard this term used with C++ before. Can you explain more? Ideally: Can you give an example snip of code that demonstrates it clearly?
Its a set of rules, used by defense software, they are available on the internet
For example the failed F-35 project used it. Seems pretentious and risky compared to using a language that is safe by default.
What language do you propose?

(I'll just pre-empt that if you say "Rust", Rust wasn't around until recently and the F-35 project started in '93. These things span decades, while only a few programming languages do)

C++ is a pre-standard "Eh, just do whatever" language in 1993.

Bjarne's 2005 JSF rules have the same effect as an "Employees must wash hands" sign. It's not the billion dollar fast food chain's fault that a minimum wage employee didn't obey the sign and now you've got food-borne illness. They put a sign up!

He always misses the amount of avionics bugs that the F-35 suffered from, in spite of the rules.
The incredibly obvious answer is Ada, given the DoD commissioned it and the fact that it was used for the F-22.
I wonder if DoD desire to tap into a bigger pool of C++ programmers also brought a lot of people who was not trained to write a high-reliability code.
Ada is far safer than Rust (not in edge case memory allocation problems, but in day to day application programming), and not only existed at the time, it was the industry standard for aviation (for good reason). Entire educational programs and pipelines existed for it.

Boeing and other defense contractors dropped it because C++ programmers were cheaper on paper (not realizing/caring that good C++ engineers were more expensive).

One of my current coworkers used to work on on-board systems for military aircraft. Anecdotally he tells me the critical systems for the ones he worked on were Ada but other systems could be C++.
In what sense was the F-35 project a failure?
Total cost due to avionics issues and other construction failures.
Username checks out :-)
I think you're thinking of https://en.wikipedia.org/wiki/High_Integrity_C%2B%2B

I wrote a comment explaining what in my mind distinguishes "high reliability" (defensive programming and making invariants/error cases/intended use explicit) C++ from regular C++. IMO it basically boils down to contemporary "Google/fintech style C++", which is a different development culture and ecosystem from defense/automotive

The biggest split is not using exceptions with aborts on memory overflow. It alters the programming style to such extent that it feels like a different language.
Top 2 Google search result are ..: this post and this article
Google give enormous priority to new content, especially on very well referenced and active sites like HN. So it probably doesn't mean as much as you think.
Assuming the original commenter is referring to essentially best-practices defensive C++ like you see at Google and some projects like Envoy proxy, and the other reply is thinking of high integrity C++ [0] (a proper noun form of C++, whereas just writing reliable C++ is less proscriptive):

Here's an example that uses compile time type assertions (static_assert, C++ can already do this), runtime errors (CHECK, standard Google/abseil practice for explicitly handling invalid states and invariants), test/dev checks (more of a defensive programming inline test than a pre or post condition), and wrapper/error handling types to do the same kinds of things as you might think to use contracts for.

  template <typename T>
  absl::StatusOr<double> Percentile(std::span<const T> sorted_values, double p) {
    static_assert(std::is_arithmetic_v<T>, "T must be numeric");
    CHECK(p >= 0.0 && p <= 100.0) << "p out of range: " << p;
    DCHECK(std::ranges::is_sorted(sorted_values)) << "input not sorted";

    if (sorted_values.empty()) {
      return absl::InvalidArgumentError("empty input");
    }

    const std::size_t last = sorted_values.size() - 1;
    const double rank = p / 100.0 * last;
    const auto lo = static_cast<std::size_t>(rank);
    const std::size_t hi = std::min(lo + 1, last);
    const double result = std::lerp<double>(sorted_values[lo], sorted_values[hi],
                                          rank - lo);

    DCHECK(result >= sorted_values.front() && result <= sorted_values.back());
    return result;
  }
(I used AI for the function impl, only need it as scaffolding to demonstrate the contract-adjacent, non-implementation code)

Before I was exposed to this style of C++ and learned to write it this way, it basically felt like a different language. You often hear people say that the C++ standards committee and language designers seem to have different priorities and developer culture vs most big tech companies/finance and I think it's because even if they're aware of the features and tools that come out of Google (et al) [1], they don't use them in their current day to day jobs and want that functionality in the core C++ toolchain.

IMO the problem is that a lot of what they want to add to the language is already "solved" by third party tooling, but because for whatever reason they don't use those existing solutions as part of their everyday work, they sometimes come up with language features that overcomplicate or solve the wrong thing, in a way that you would intuitively understand if you were already regularly using 3P tools to solve them.

I could also be the one misinterpreting things here so apologies if this is obvious or not what the original commenter meant by "high reliability".

[0] https://en.wikipedia.org/wiki/High_Integrity_C%2B%2B

[1] https://abseil.io/about/ is one of many third party ways to make C++ less insane

If you squint hard enough your example does look a lot like Ada pre and post condition contracts (perhaps a bit less ergonomic, at least for someone who hasn't written C++ in a while).

At this point the rust contracts crate with requires/ensures looks like a more straightforward approximation of Ada's Contracts and assertion policy. But still as far as I am aware no one has implemented something that mimics the static proof functionality in Ada's SPARK subset (which arguably not all applications or problem domains actually need or can justify the extra effort/cost).

> IMO, a lot of what they want to add is already "solved" by third party tooling,

https://news.ycombinator.com/item?id=50364593

I haven't seen any good examples of contract preconditions that I would actually want to use. What I've seen is stuff like

  double safe_sqrt(double x)
    pre(x >= 0.0)
    post(r: r >= 0.0)
  {
    return std::sqrt(x);
  }
Preconditions violate the principle of "make invalid types unrepresentable" but look like they're helping. They are basically a oneoff extra specific type that (if the state you're checking is worth checking at all, it must be representable in the actual argument's type) contradicts the actual argument's type. So why not change the argument's type directly?

Because it's hard, or not possible, for the same reason that most of these preconditions aren't generally statically verifiable.

Suppose your precondition is x > 5. Statically, you can stop someone from directly passing a literal <= 5, detect locally declared variables assigned to numeric literals and do the same. But to generally infer whether any argument satisfies specific properties quickly gets extremely complicated, because how can you generally verify that the calculations done to a const or literal within the caller's scope guarantee certain properties about the output, without actually performing the calculation? You can come up with cases where you only add to an int and you see it was initialized to 0, so you know it's never < 0 barring underflow. Those are the easy cases

If the caller is passing in something derived from their own arguments, or from I/O, all bets are off. All you know is that the argument has a type, and its value was derived from unknown inputs. So you need a runtime check to actually assert your precondition and make it behave like a type check. But then what happens if input doesn't meet the precondition? Do you throw an exception or crash?

I think that there should be a reference implementation for a useful static analyzer for preconditions, for it to be added to the language. Obviously it would be nice if you could verify that callers only pass in x > 5 to your function, but I think deferring the semantics for contracts to however the build/compiler chooses to handle them (because they might, one day) is not good enough for adding a new feature and syntax to a language. If preconditions can be used for useful static analysis beyond what static asserts and the type system gets you already, there should be evidence for that. I'm skeptical that you can do any better than a regular static assertion/type checks.

Also, I do think the lack of explicit handling (if in practice preconditions are only generally evaluable at runtime) in the contracts syntax is bad. The proposed syntax looks too much like a type or static assertion for a runtime check (note that you can easily see what CHECK/DCHECK macros actually do just by clicking through to their definition). And if it isn't in practice just a runtime check, there should be proof!

> If the caller is passing in something derived from their own arguments, or from I/O, all bets are off.

This is the part of contracts that I don't understand. I suppose you could (1) runtime validate any user input to the program and then (2) chain multiple functions like `safe_sqrt` that provide pre and post conditions.

In theory, this should allow the static analyzer to reason about any arbitrary input. However, this to me raises even more questions: is this practical, is this possible and why would I not try to achieve the same through types ("make invalid types unrepresentable"). Maybe I'm completely off the mark here.

The problem is that the current design doesn't take into account binary libraries, or what happens when conflicting contract modes are linked together, as contracts aren't reflected on ABI.

Additionally they offer very little mechanisms versus Eiffel's original design, Ada/SPARK or Frama-C.

A basic MVP, expected to improve on subsequent C++ version, assuming that the proposal authors stick around for those evolution proposals.

Correct me if I'm wrong, because I don't follow C++ very closely, but based on previous discussions on HN, the opposition paper obliquely referenced in the blog post was presumably Bjarne Stroustrup's, who IIRC had already said he would work behind the scenes to make sure the final pro forma vote to standardize C++26 would fail.
> Correct me if I'm wrong, because I don't follow C++ very closely, but based on previous discussions on HN, the opposition paper obliquely referenced in the blog post was presumably Bjarne Stroustrup's (...)

I've noticed that Bjarne Stroustrup is being subjected to a smear campaign, when things are far simpler and far less conspiratorial than they are making out to be.

There are indeed papers demonstrating that not only is the current proposal for contracts broken but it also fails to adhere to core C++ principals. They have been published since at least 2017. Contracts aren't nee, nor the problems they introduced. They've been routinely removed from C++ standards, and so far the proposal wasn't fixed.

So ask yourself this: why was a notoriously broken feature forced into the proposal when it was clear it wasn't going to pass?

From an outsider's point of view, I see this from a different perspective. Contracts proponents tried to use bureaucratic tricks and threats of abnormal processes to force a broken feature they knew for years that wasn't supported or passing the smell test. And now that they saw their efforts thwarted , the complain that their plan failed and they have opposition?

I mean, there is even a paper dating back to 2025 called "contracts concerns" and from 2026 called "contracts fundamental flaws". The C++ standard is a consensus-driven process. Does this look like consensus? Clearly no.

So we have a group of people who ignored the calls that they were pushing a broken feature, but tried to railroad the process anyway and ignore any concern or warning. Then, when they tried to force their way through the process, their bluff was called and their threats failed. And now they are lashing back.

I have no horse in this race[1], and tried not to use opinionated language. Of course there can't be a conspiracy when Stroustrup said what he was gonna do beforehand. But IIUC there was already a two-thirds majority to finalize the draft, so that's hardly railroading.

[1] I'm still in the C camp, and don't write C++, but contracts seem of dubious value given the lack of guarantees about whether something can be compile-time vs runtime enforced. It's sold as a safety thing but in reality it seems the value is more about optimization & performance and potentially could cause security issues of it's own.

I would really love to know: who are the people pushing the current version of contracts, who do they work for, and why does the current version of contracts meet their needs if it's so flawed?
> I would really love to know: who are the people pushing the current version of contracts, who do they work for, and why does the current version of contracts meet their needs if it's so flawed?

It seems the lead author and champion is a guy from Bloomberg, of all places.

https://isocpp.org/files/papers/P2900R6.pdf

As the story goes, these guys pushing contracts systematically pushed a broken proposal by dismissing criticism with bureaucratic chicanery such as purposely ignoring feedback and criticism by claiming that if other people voted in favor of their proposal then they shouldn't need to bother with feedback from those who opposed.

I mean, look at the reaction. It's not technical. It's not principled. It's bureaucratic, and dismissing yet again a failure to gather consensus as personal attacks and a political issue.

> As the story goes, these guys pushing contracts systematically pushed a broken proposal by dismissing criticism with bureaucratic chicanery such as purposely ignoring feedback and criticism by claiming that if other people voted in favor of their proposal then they shouldn't need to bother with feedback from those who opposed.

From what I've seen of the story, the opposite is true. The people opposing contracts are the ones who have been engaging with bureaucratic chicanery to try to rip it out of the standard. In the discussions within the committee, they've been given every opportunity to make their case and had their arguments heard, even when those arguments failed to persuade anyone and are simply relitigated again and again in subsequent meetings as if they're new. In at least one national body, the anti-contracts people used the bureaucratic process to change the vote of the national body.

> I mean, there is even a paper dating back to 2025 called "contracts concerns" and from 2026 called "contracts fundamental flaws".

Two papers that both have the same authors, one of whom is Bjarne Stroustrup.

Why are you convinced the narrative is that contracts are actually broken and unfixable instead of a few influential people just really hate it for reasons they have been unable to convince anyone else are valid?

Have you read the "contracts fundamental flaws" paper? Looking at it now, it's hard to take it seriously. The biggest complaint seems to be that the marketing of contracts is wrong. Literally: "We would welcome a contracts design that is simple, and “marketed” as just a debug aid, rather than a safety feature."

It really does look like Bjarne is convinced that profiles are the future for C++, and contracts makes it less appealing to get there. And that's something that reasonable minds can just disagree about without it being a conspiracy of some kind. WG21 doesn't seem to believe that profiles are an anytime-soon-if-ever feature, and contracts provide immediate benefit that justifies any future complications with profiles.

Bjarne Stroustrup has been pushing Profiles, which would allow C++ code (or the majority of it) to become type-safe and memory safe.

Contracts are useful, but don't guaranteed anything if type safety & memory safety can be bypassed.

I think the ISO panel made the right call. The real world consider memory safety & execution integrity to be critical issues, and C++ no longer to be viable. Without some major improvements -- I would consider this view to be correct.

> Profiles, which would allow C++ code (or the majority of it) to become type-safe and memory safe.

Certainly safer, but not memory safe. Operations as simple as multiplying signed integers or popping an empty vec can be undefined behavior which is not memory safe.

For most domains, it is fine. Why should my valued checked code pay the price for checking every arithmetic operation for overflow. Why should my correctly implemented algorithm waste CPU checking something I know is valid? And worst of all, what happens when a logic error is encountered, we run untested code path? I hate code that is conditionally defensive (eg. if (ptr) ptr->critical(); ). I should never be in that situation, a silent ignore corrupts internal state, and never tested the fail path. Ptr may even refer to garbage. Its a stupid defebsive check in 90% of code bases. std::optional<Ptr> at least clarifies intent.
The problem is that it silently overflows by default - and a good chunk of the time it is even undefined behavior. Sure, in some situations you as the developer are 100% certain that an overflow is impossible (despite the compiler not being able to prove this and therefore eliminate the checks), but in the vast majority of cases it is a footgun silently waiting to go off.

Rust tries to solve this by having basic addition panic in debug, while silently-but-consistently continuing in production: overflow is considered a bug, but it is at least not a platform-dependent bug.

If overflow is expected, then there's checked_add to detect it and fail in a friendly way, saturating_add / wrapping_add / carrying_add for specific overflow behavior.

Finally, if speed is crucial and overflow is either impossible or you don't care about the outcome whatsoever, there's unchecked_add to explicitly opt-in to a C-like "just do whatever the machine feels like".

You can still do everything you can with C. It it just an explicit choice, rather than an implicit platform-dependent mechanism you might forget about.

> unchecked_add to explicitly opt-in to a C-like "just do whatever the machine feels like".

Just like for signed integers in C the {integer}::unchecked_add is Undefined Behaviour if overflow occurs. So that's not "whatever the machine feels like" it's much worse.

This is an unsafe function, so you're expected to write a SAFETY rationale for the unsafe call, and that's your opportunity to justify to a future maintainer why you were sure this addition never overflows. If you find yourself struggling to justify that belief it probably means you should not have used this function.

If you're going to write guard code for overflows, and use that to justify the SAFETY claim, why not use the existing functions for that? Clippy will suggest this in many cases because it's less likely you will blow your own foot off.

I like the Employees Wash Hands sign. Recent batches of API tools seem focused on sanitizing IO: WebMCP, AI strings, safe native input parse, even Assembly mapping. So in a hot loop (whatever F35 anonymous lambda) you may have data change under you. So on antiquated hardware (like a Voyager I) maybe you want to flash the firmware to 3.5 after 70 years... but Iran has a HELLIOPARSER. It's imperative to be defensive transmitting data streams across the light years.
Yep. Safety and simplicity need to be the priority.
> Profiles

Contrary to Contracts, which at least managed to get consensus in WG21, I very much doubt that Profiles will get consensus.

Profiles are vaporware
I used to be a C++ programmer but I haven’t done it in a few years.

I pretty much do all my low level vibe coding in Rust. Is C++ still relevant? What prevents Rust from completely supplanting it?

99.9% of all system code in the world is still written in C/++. It runs your Java, C#, Javascript, Python, PHP, basically every production language that isn't Go or Rust. It runs the two most popular game engines in the world. It runs your phone, server, and laptop, no matter which of any you use. It runs your car. It runs almost every embedded and industrial application on the planet.

Is it still relevant, JFC. The way people on this forum manage to sequester themselves from reality. Let me reverse the question: is Rust relevant? Mozilla developed Rust, abandoned their Rust browser, and only 10% of Firefox is written in Rust. Maybe 1% of modules in Chrome and Linux are written in Rust, if that. And what of Rust applications written from scratch? Can you name ten applications that have, say, exposure to more than 100,000 users? Impossible mode: they can't be developer tools only used by other developers (uv, ripgrep, etc.), they must actually be applications used by enterprises or consumers.

> basically every production language that isn't Go or Rust.

Even in their case. Rust depends on LLVM which is wriiten in C++. Go needs libc on some platforms.

C++ is the third most popular programming language according to TIOBE behind C and python. It's got an 8.87% ranking. So yes it looks like C++ is still relevant. In fact C++ usage has risen slightly.

Rust is in tenth place with 1.44% ranking, it's rising fast but still has a long way to go before it catches C++.

I'm not going to speculate about why Rust hasn't yet supplanted C++ but I will say I don't find it surprising.

TIOBE is nonsense.

But, of course, there is still a lot of new C++ code written, more than Rust. I believe C++ will become legacy, but it's not there yet and even once that happens it'll take at least decades to stop writing C++.

Please for God's sake stop citing TIOBE.

A much more accurate snapshot would be Github - they recently published the top langauges for the year (so far, up til Sept 2026) by distinct monthly contributors and C++ comes in at 9 out of the top 10, and Rust doesn't even place in the top 10 yet, so yes it is highly relevant and prevalent, but not because TIOBE said so.

But, TypeScript, Python and Rust are the fastest growing languages, in that order, so also you cannot discount Rust.

https://github.blog/news-insights/octoverse/octoverse-commit...

You didn't mention why people shouldn't cite TIOBE so I checked. It's because they measure search engine queries to assess popularity. GitHub measures actual code usage in real repos.

I agree the GitHub methodology seems better. I don't think TIOBE methods mean that it's ranking is completely irrelevant but it'll be noisy and you could easily game it.

Github is also skewed because it only captures a subset of open source projects, and open source is realistically a teeny tiny fraction of the world's written code.
Yes, GitHub is heavily skewed towards "hip" projects.
Even if C++ is irrelevant for new code, there's so much software already written in it that we'll be maintaining it for decades to come. I'd argue that Cobol and Fortran have been mostly obsolete for new code for almost 30 years now, yet both are still widely used today, and they've even had major updates in the past decade [0] [1]. And there's even more software written in C++ than there is in Cobol or Fortran, so I don't think that C++ is going away any time soon.

[0]: https://en.wikipedia.org/wiki/COBOL#COBOL_2023

[1]: https://en.wikipedia.org/wiki/Fortran#Fortran_2023

with ai their future seems very uncertain. ports are now very easy, so languages have to stand in their own merits
That is a myoptic view. Old codebases often have their value measured in the tiny problems thay were ironed out over the decades and the knowledge that they cover their subject domain correctly. A complete rewrite loses all of this in an instant amd has to start from scratch.
Essentially all high-end systems code for high-performance and high-reliability systems is still written in modern C++. That language has many attractive properties, including safety features that Rust does not currently support.

Additionally, for pure performance requirements, C++ is still materially faster than Rust in practice. That may change some day. C++ has many issues but it is also objectively excellent at many things.

> That language has many attractive properties, including safety features that Rust does not currently support.

Could you expand on what specific safety features C++ has that Rust doesn't?

> Is C++ still relevant? What prevents Rust from completely supplanting it?

A highly mature ecosystem with well-established libraries. Especially in certain fields (DSP, robotics, CAD kernels, microcontrollers, etc.), there are no equivalent libraries and frameworks in Rust with such a proven track record.

Now, LLMs can rewrite those libraries in Rust quite easily. Such options weren't available a few years back. But it's still hard to prove that a rewrite hasn't introduced new bugs. It's easy to demonstrate that a piece of code has bugs, but much harder to prove that it doesn't introduce any new ones.

Additionally, even if an LLM-created Rust port of a C++ library was bug-free, an LLM cannot recreate the community that has evolved around the library.

Take PROJ for example, which is the de-facto coordinate systems library in the geospatial world, mostly written in C++. The processes and trust built up with external organisations like national mapping agencies is irreplaceable.

That hasn't stopped people trying to vibe-clone PROJ in Rust though.

> ...an LLM cannot recreate the community that has evolved around the library.

This is, in fact, an excellent point. You can ask an LLM to expertly clone or re-create any project in a different programming language. But that doesn't make you (or anyone else) an expert in that field, let alone competent in such a new codebase. Slowly developed, painfully debugged projects have a community of human brains who care about the topic. An LLM clone has nothing like that.

> contracts. Put simply, a number of NBs believe that this feature is not yet ready for release.

The ISO National Bodies voted wisely. C++ has had so many ill defined features over the decades and they wanted to avoid yet another one.

I don't have any skin in the game. I've stayed with the C++11 feature set.

Constraining yourself with the C++11 feature set in the age of agentic coding, yikes.
Using C++ in the age of agentic coding, yikes
Not using C++ in the age of agentic coding, yikes
Agentic coding is only possible thanks to C++, not Python.
Hm, the wikipedia page of pytorch doesn't list C++ as language, just C and Cuda.
The Wikipedia page of PyTorch does list C++ as a language. And you can just check the code. It's C++.
CUDA is C++, Fortran, and C, plus anything else with a PTX backend.

However the main language for CUDA is C++ since version 3.0.

Documentation is available on NVIDIA website.

At this point, changes to major programming languages have to adapt to a world in which AI systems generate and change much of the code. C++ contracts may be good or bad, but they are from before strong AI coding systems. So it's time to rethink.

And we have no idea what AI systems will be doing in 2027.

A lot of folks, many of them our most capable programmers, are fighting the last war. It’s like they think AI is going away and we’ll all work like it’s 2019 again.
It looks like 2027 orb2028 will be the year when everyone gets so fed up with AI that those "features" will be forced to retreat from under everyone's nose. The stuff will not go away, but there is AI fatigue and it is slowly approaching a tipping point.
What makes it go away? People can reject datacenters, AI slop(to the degree they can detect it) and AI search results, but what stops the wave of automation coming for SWEs and IT workers? We are the least able to resist. AI already does a better job than the majority of us. It is, even with much higher token costs, vastly cheaper. So what shoves it back into the box?
It won't go away, but people ar getting tired of the UX everywhere force feeding AI "features" to them.
Not to defend the particular proposal at issue here, but my sense is that contract-like things synergize quite well with AI coding, for the same reasons automated tests and static types do.
> So it's time to rethink.

>

> And we have no idea what AI systems will be doing in 2027.

How would you begin to form a plan of how you'll rethink if you can't even see into next year? Isn't it beneficial not to change the languages too much because there's so much training data for the current revisions? AI does not need to be catered to, that is the whole point and why it is useful.

We're going to need languages which both humans and AIs can read and write. We don't know what those look like yet. Contracts aren't a bad idea, but C++ has just become too big. Even people who used to be C++ language lawyers have said that.
Wow. I’m surprised at the amount of downvotes. Are people really that in denial?
That surprised me, too. This was marked down to -4.
C++ should focus into turning SIMD into a higher level language instead of being a giant collection of intrinsics. Avx code is unreadable.
SIMD cannot be solved at the compiler level. The capabilities of silicon SIMD implementations are fundamentally so disjoint that code using SIMD requires contextual and platform-specific data structures and algorithms.

SIMD on different silicon is incompatible at layers of abstraction far above the codegen manipulation a compiler can do.

You'll never get the full feature set of all SIMD implementations in a single generic abstraction but I'm not sure that's the only way a SIMD abstraction could provide value. There is a pretty consistent set of narrow SIMD that behaves close enough to consistently get better performance across generic targets with high level abstractions better than auto vectorized scalar code but worse than platform tuned SIMD.
The subset of SIMD that translates is so narrow that it is almost useless in real code. That’s the problem. Additionally, it is invalid for the compiler to redesign your data structures.

The ability of compilers to use SIMD is no better than it was 20 years ago. Total stagnation for all practical purposes, and the reason is that compilers fundamentally lack the context and freedom to rewrite the code architecture appropriately for SIMD optimization (even if they could).

I think a point people miss is that highly optimized SIMD code is almost never about parallelizing loops. It is about deeply probing and manipulating arbitrarily complex data structures in parallel that involve collections of unrelated types. SIMD allows you to do this, and it is fantastically efficient, but a compiler has no conceivable way of understanding this.

For this reason, SIMD optimization has often been classified as an AI-Complete problem in computer science.

Couldn't SIMD features include marking data as "the compiler is free to rearrange"?
Only in the trivial cases where the compiler already knows that. Data used inside a single function can already be rearranged. Data that is used across more than one function can be rearranged only in the case where the compiler can prove the function is only used in the one translations unit (that is files). If data is used across translations units, there is no way for the compiler to talk with the compiler of the other translations unit to agree on the data rearrangement.

There is some effort in whole program optimization which can solve the above problem in theory. However I don't know how well it works in practice.

My imagination is failing me, can you give me an example of the type of work being done where SIMD is ‘deeply probing and manipulating arbitrarily complex data structures in parallel that involve collections of unrelated types’? I don’t doubt you know what you mean, but I can’t wrap my head around it.

For me I can only think of the simplest example of SIMD being used to ‘parallelize loops’ as what SIMD is for. If it turns out I’m missing a large problem or application space for SIMD I will be excited to research it. Any pointers to topics would be appreciated.

One example is OLAP databases, which often heavily exploit SIMD for query processing. You can also turn parsing into a SIMD problem, which is applicable to things like handling XML, JSON, and CSV. Simdjson comes to mind, or parabix for XML.
The parsing stuff I am aware of, but the query processing is a big blank for me to dig into.
SIMD is often used to evaluate complex data structures in parallel. A common case is given a row with an arbitrary mix of data types and a query with an arbitrary mix of independent constraints on those data types, to evaluate all of the constraints in parallel in the same SIMD instruction(s).

The idea that SIMD is only good for parallelizing operations over arrays of the same type is empirically false and seriously understates the capabilities of good SIMD implementations. Some SQL-ish implementations work this way on row-structured data.

Most devs seriously underestimate what good SIMD is capable of.

Thanks for the response, I’ll have some reading to do in this area.
Portable SIMD works for me today, not sure why you're unable to find use cases for it?
Is the common feature set described anywhere online? I am not in the SIMD world, and I am curious about the state of it. But I am not so committed that I am wiling to learn several different platforms’ SIMD implementations in order to suss out their commonalities.
If you want something real high level, check out WASM's SIMD. They limit things to 128 bit widths and common operation.
That's why it needs a lot of work. Writing SIMD in c++ is like writing assembly.
Please stop repeating this ludicrously overstated claim.

I have personally seen several hundred use cases for SIMD that are just fine with portable intrinsics, and NOT always "platform-specific data structures and algorithms". Sure, that does happen, but not fundamentally, nor even often.

To be clear, I agree the compiler isn't solving the data layout problem for us, but portable intrinsics are indeed useful.

gemma.cpp uses them, and last I checked, has much faster long-context prefill and decode vs. llama.cpp. They hand-roll the intrinsics and presumably it is harder to land optimizations repeated across 7+ implementations/instruction sets.

There are frameworks trying to unify simd/avx, but the abstractions aren't free. At this point, we need better hardware and low level interfaces, not better abstractions.
In fact, C++26 made some considerable progress on that front.

https://en.cppreference.com/cpp/experimental/simd

An implementation of which exists in the following GitHub repo (albeit implemented in the xvec::simd namespace rather than std::simd...but otherwise intended to be spec-compliant).

https://github.com/intel/xvec

Speaking as a long-time C++ developer...I wasn't uninterested in contracts (which I've known about since the days of Bertrand Meyer flogging them in Eiffel), but I agree with the sentiment here that the SIMD efforts were considerably more interesting.

Approval of runtime failures essentially failed at runtime
hmm, i rather think this is implementation time, pre commit. it failed the tests.

runtime would be after commit when the standard is released and moved to production and users fail to make their code with the new features work.

But I'm curious—why did DIS fail this time with C++26? Weren't feature additions in C++ usually plentiful?

But they say this is the first case where a DIS failed during the standardization consensus process. Why is that?

> By voting “no,” an established system, one based primarily on trust and respectful collaboration, has been shaken.

I don't get it. If ISO deliberately requires two levels of approval, why should exercising the second level's voting authority be considered a betrayal of trust?

I don't get it either; and have no sides on the fence (been years since I wrote C++; but I have before).

It sounds like there's sufficiently different genuine views here on whether it's right for the standard at this time, and this seems like the process working as designed.

Because they didn’t vote the way the author wanted them to.

That’s not very charitable, but honestly I’ve been trying for five minutes now to find or think up an alternative explanation. And coming up blank.

A more charitable interpretation is something like royal assent for laws. Yes, the king/queen can always just choose to delay it or even block the law, but that'd be unprecedented and the whole system of parliamentary monarchy would be in a serious crisis.

I think the author is trying to get at like, the actual discussion happens earlier / on the WG21 level, and the ISO vote is treated more of a rubberstamp. And that has changed in this instance.

Personally, I think that if a system to veto something exists, it shouldn't be considered shocking or a betrayal of it gets exercised. Otherwise why have the system?
> but that'd be unprecedented

Not really. The unprecedented part was how come contracts proponents decided to push a proposal against all feedback and concerns, knowing very well it was falling to build up any form of consensus.

Contracts proponents knew for years the featured proposal was opposed as it was riddled with fundamental technical flaws. The unprecedented part was the way they said "screw them" and pushed forth anyway, hoping the formality would build enough pressure to force anyone opposing the feature to succumb to the bureaucratic pressure and silence their concerns.

This contracts stunt reeks of corporate chicanery. I mean, what was the plan here? Ignore everyone, get the bureaucratic foot in the door, and then blackmail all dissenting voices of sabotaging the process if contracts proponents didn't had their way?

"Any form of consensus": there was obviously consensus in WG21, hence contracts remained in the draft.
> "Any form of consensus": there was obviously consensus in WG21, hence contracts remained in the draft.

Contracts have been systematically pulled from the drafts since C++ 2020 as their proponents decided to ignore technical feedback and opted to go for political petty tactics much like those we see today.

Ask yourself this: how come the contracts proposal has been floating for so long, changed so little, have no reference implementations that address any remarks, and you still see the half baked proposal being floated?

And WG21 members did voted against it. Contract proponents repeatedly try to dismiss critics as having been ignored due to the nature of the democratic process, and now are complaining that they themselves see the same democratic process rejecting the proposal yet again, this time after the unprecedented push.

> And WG21 members did voted against it.

Not most recently, when it was first voted in, then repeatedly voted to remain in when the option to remove it was polled. The most recent consensus of WG21 is reflected in the current draft, established by multiple votes overwhelmingly in favor.

But receiving a majority vote is not the same as building a consensus. I think that's the sticking point here.
It wasn't voted out of the blue. There was extensive discussion prior to votes (including weekly telecons for months solely dedicated to contracts). So how do you measure consensus if not by a vote after extensive discussion, leaving everyone to voice their opinion, come up with alternatives and propose polls?

And sustained opposition does not necessarily mean lack of consensus either. WG21 heard the opposition and decided that constracts belong in the proposed draft despite of that opposition. It is very rare that a new feature does not get opposition, even a sustained one.

Now it is clear that there is no consensus between WG21 and the national bodies (although they overlap), but there is clear consensus within WG21.

The definition in ISO/IEC Guide 2 for consensus is this:

> Consensus: General agreement, characterized by the absence of sustained opposition to substantial issues by any important part of the concerned interests and by a process that involves seeking to take into account the views of all parties concerned and to reconcile any conflicting arguments.

So to me it is not at all clear that there was consensus within WG21.

John Spicer, the former chair of SG21 (the C++ Contracts Study Group), also seems to have doubts about that, see <https://open-std.org/JTC1/SC22/WG21/docs/papers/2026/p4381r0...> -- which is quite self-critical.

Don't get me wrong, I am not taking sides here (I haven't even done any work in C++ in the last 10 years), but it does seem a bit more complex than how you paint it.

> So to me it is not at all clear that there was consensus within WG21.

Not only was there no consensus, reports from the process described the behavior from contracts proponents in WG21 as political maneuvering and trying to ignore criticism by pretending that somehow consensus was not a goal and thus they could simply nominwlly reject and ignore any criticism.

There's a lot of personal attacks directed at Stroustrup but somehow it's left out of the story the fact that Microsoft apparently criticised the proposal as unimplementable. We're talking about feedback from the dominant compiler vendor.

I appreciate that ISO/IEC tries to provide some definifion of consensus, but it's so vague that is borderline useless. Who decides what is "important" or "substantial"? Do we need an other round of consensus for that (making the definition circular)? Or is deciding what is "important" or "substantial" part of the process that is outlined in the second part of the definition (making the first part more or less redundant)? Or is it the opposition to decide if their presented issues are "important" (making it effectively a veto power)?

As for the second part of the definition, regarding the process, that all took place with a measurable outcome. Although "reconcile any conflicting arguments" might be interpreted as unanimity, but that's surely not the intent.

> I appreciate that ISO/IEC tries to provide some definifion of consensus, but it's so vague that is borderline useless.

Is it though?

I mean, in what world does the concept of consensus means it's ok to ignore all opposing remakes, criticism, and objections?

You have a proposal for the C++ standard which representatives from companies such as Microsoft rejected after describing it as being unimplementable, and knowing this it's supposed to be fine to push forward with it?

What was the plan here? Are these guys so out of touch that they thought petty political chicanery would compensate all the technical problems?

At some point a minority needs to accept they have lost.

I've been following contracts for a while and my interpretation is some people are refusing to accept that others disagree with them. These people are repeating the same arguments that have been addressed multiple times.

You can disagree, but I look at it as people refusing to work with others voting no.

The vote for incorporating contracts into C++ was 100 in favor to 12 against.

Consensus is not the same as a majority vote. But it also doesn't mean that a small minority gets the right to block the feature forever.

> Because they didn’t vote the way the author wanted them to.

That's my opinion as well. It's a smear campaign lashing back at people who dared to point out flaws.

The Section "The Process" does explain the thinking behind that statement. To rehash: The author thinks that NB's were trusted with the ability to reject by blocking minority for the case that there is new information, but have used that ability in a case where there was no new information.

I have no stake in this entire discussion or C++ and don't know if the premise of this argument is even true. Just curious: is that thinking unhinged?

Note that the author says that this was "the previous practice". There is no mention of this being, say, the sole intended use as mentioned in some bylaws. In fact, if "uncovering of new information" was the sole reason, why not have a confirmation vote in the same body after a mandatory cooldown period?

The author even explicitly states that "errors in the process" are another potential reason for the NB's to vote against a proposal, so why focus solely on the "no new information" argument?

Also, keep in mind that the WG21 operates primarily by consensus[0], which is explicitly not a majority vote. The final vote for Contracts was 114 in favor, 12 opposed, 3 abstaining, which some consider "an unusual level of opposition" with "tangible debate"[1].

I assume the default is for people to trust that the domain experts in the various subcommittees did their work properly, so an in-favor vote would be more a "I trust the subcommittee / I don't care about this feature" than an explicit "I approve of this feature", with an opposing vote basically being "the subcommittee is making a grave error, this is obviously going to blow up in our faces".

Extend this to the NB level, and the disapproval is basically a vote of "Wait, do we really want to standardize something which is still facing very serious opposition?"

[0]: https://isocpp.org/std/standing-documents/sd-4-wg21-practice...

[1]: https://componentsprogramming.com/cpp26-croydon-wg21-meeting...

Because the second level isn't really involved, they are a formality. This isn't unusual, it happens when the range of things a group does has grown so large that it needs to be primarily managed by dedicated subgroups but the rules don't update to delegate all authority to that subgroup.

The members of the broader group that cared strongly about C++ would have just been involved in the WG21 subgroup in the first place, the subgroup that approved it with a 2/3rds majority. So it almost certainly means that a broader group of ISO that normally don't care about what C++ does (and hence aren't involved in WG21) were influenced to vote in the direction the minority of the WG21 wanted.

major C++26 features, including reflection, std::execution and library hardening, are also delayed because they were included in the same draft.
No they are not. The standard may be delayed but most compilers ship these features already.
They are shipped experimental and most people will not use them. Even those who use them will limit use as they have been burned before by something experimental changing when it was finally stable.
While I can understand that C++ contracts were met with controversy, contract annotations scoped at analysis time that can be verified by external tools, such as static analyzers, model checkers, or automatic theorem provers, are incredibly useful.

I put together an alternative function contract and invariant mechanism in C using CBMC and custom macros that effectively allows me to perform formal methods in C using compositional verification. The reason why I chose C is because of its relative simplicity and relative ease of building tooling around it. C++ contracts provide some feature parity, and would let me take advantage of some of the features in C++ relative to C.

I hope that the contract proposal is workshopped and simplified so it can be proposed again for a future version. Its current form is unsuitable, but it deserves a second chance with a simpler implementation. Contracts would narrow the safety gap between C++ and languages such as Ada / SPARK.

Contracts are useful, but don't guaranteed anything if type safety & memory safety can be bypassed.

I think the ISO panel made the right call. The real world consider memory safety & execution integrity to already be critical issues (and C++ no longer to be viable), and they are correct. The WG has its priorities wrong.

Memory safety can also be bypassed in Rust. If you want something where memory safety is guaranteed, use Fil-C but this comes at a performance cost. Or use formal verification, where then contracts can help (but C++'s complexity doesn't).
I was surprised to discover recently that C++ is in a pretty nice sweet spot for verification (at least at the binary level), where it has some useful type system features, but will get out of your way and generate simple ASM (without e.g. spamming bounds checks and panics everywhere as rust does).
This is like responding to someone saying that someone can die from an getting shot accidentally by a gun by saying you can also die from drinking too much water. Both of them are technically true and do happen on occasion, but one of them is not nearly as much of a risk in most circumstances, whereas the other is pretty much inherent to the most basic way of using it.
No, I do not think that this is comparable. This just the annoying exaggeration I complain about. In reality, one can write fairly safe C code, while Rust code in practice is also far from perfectly safe and also introduces new supply chain risks.
I don't agree at all.

> one can write fairly safe C code

In practice, pretty much every C/C++ codebase in existence has ended up having memory safety issues, even very widely used ones with a lot of scrutiny over the years.

> while Rust code in practice is also far from perfectly safe and also introduces new supply chain risks.

You're conflating "does not have one notoriously dangerous type of safety issue" and "does not have any safety issues", which is a disingenuous characterization of what I said. You were the one who introduced the comparison to memory safety in Rust and C++, and now you're moving the goalposts as an attempt to rebut my disagreement.

C and formal verification is an awesome combination. I tried cmbc on some toy programs, it it fully automatically proved memory safety and all assertions. But for larger programs one has to split up with a contract-like facility.

Can you tell us more how you use cbmc with macros? I am also exploring such tools.

I also wonder what feature from C++ you miss in C?

Well i you ask me i miss namespaces and functions i could put into struct and enum types
> contract annotations scoped at analysis time that can be verified by external tools, such as static analyzers, model checkers, or automatic theorem provers, are incredibly useful.

Yes they would be.

Except that's not the contracts that they tried to force down C++'s throats.

The current contracts proposals features things like throwing exceptions in contract predicates, leaves out basic features such as function pointers, and not to mention that the contract specification alone covers around 5-10% of C++ specification and still glances over most details as being implementation defined.

As everyone is attacking Stroustrup as this master mind behind this opposition, perhaps people should devote some time to read one of the many papers pointing out the many flaws in the proposal. Stroustrup himself features as the coauthor of a few of them. Why is this not a technical discussion but a witch hunt?

As somewhat of an outsider, the C++ spec process seems really strange to me.

It’s weird that major features are designed from start to finish without even having so much as a demo.

It feels like there should be a back and forth process between committee proposal -> experimental impl in a major compiler -> community feedback, and so on.

It sounds like it’s basically the waterfall approach to language design? They write a glorious spec and chuck it out to the world, and hope that compilers can implement it and people actually find it useful. Example: modules.

> It’s weird that major features are designed from start to finish without even having so much as a demo.

Not necessarily. In broad terms, Boost is considered a staging ground for features proposed to C++. Compiler projects also keep up with the standards.

In this case the concept guys continuously dropped the ball on this requirement though. One of the papers pointing the many flaws in the proposal calls out this shortcoming, where contracts have neither a workable reference implementation nor an adequate specification. In fact, they handwaved a lot over details with vague calls to "implementation-defined".

I have no idea why anyone would work in C++ in 2026. If I had to work on an existing codebase, I'd just have Claude rewrite it in Rust. It's always been a miserable, awful mess.
C++ is in a strange position.

If you look at "let's use AI to rewrite xyz in Rust", then C++ has to wonder why it isn't as often mentioned compared to Rust here. I am not saying AI should be the future, but merely compare why Rust is cited here more frequently than C++. That's just one of many other things. Rust also got popular due to crates. How is the alternative called in C++? Barely anyone outside the C++ community knows. And that's also a problem.

C++ isn't going away anytime soon, of course, but when people keep on mentioning alternatives again and again then it shows that the competition intensifed a lot.

> How is the alternative called in C++?

what is it though? vcpkgs/decentralized repositories?

With package managers on Linux, BSD and Haiku, the only odd man out needing packages is Windows, and vcpkg fills this gap so its no longer an issue.
Why would anyone want to rewrite anything in C++ given they can choose anything else? Like Rust or Go or C or Zig or literally anything else.
I wouldn't choose Rust because of compile times. C++ ones aren't great either, but with discipline in how you write code you can get to the point where you compile ~50K lines/second. Unsafe Rust is also a bit of a PITA, and I (in game engines) have cases where I care lot about precisely how memory is laid out and accessed, so I'd have to resort to it quite a lot.

I wouldn't choose Go because GC is a non-starter.

I wouldn't choose C because it's nice to have some form of generics or metaprogramming, even if templates are not exactly fantastic.

I wouldn't choose Zig because the language isn't stable, and the lead developer has hinted that they'll drop LLVM down the line, and I don't want to beta test their compiler backend.

Zig drops LLVM for debug mode only.
Because, used sensibly, C++ is a better C. This is more or less what C++98 was, and even that is probably too much.
I think Rust's saftey guarantees are an important reason to throw it at LLMs. LLMs make stupid mistakes, even the very best ones, and a lot of them, all the time. Having a compiler reject those mistakes makes for a better automated process. C++ has some safety mechanisms as well, but they're weak and fragile compared to Rust.

For people with C++ experience working together months at a time that doesn't have to be a problem, but AI rewrites turn a million lines of one language into a million of the other in a day, followed by an impossibly short human review.

Rust also isn't as safe and correct as you'd hope it to be for "fuck it, let the LLM deal with it" style programming, but it's got the best speed-usability-safety balance out of the common languages if you don't trust your programmers.

Hacker news has always been a rust bubble. Tallies of opinions voiced here are always skewed in some ways.
This article makes it sound the options are normally approval, rejection and abstention, but that this time round a fourth option, "disapproval", was reached. It that the case, or are they just trying to say that people rejected it?
I took it as the individual votes are approve/reject/abstain, and the outcome of the process is approve/disapprove.
It’s also sounding like they’re arguing the ballot should have been a foregone conclusion in which case why have the vote at all?
Honest question.

If I want to spin up a new project with a coding agent to explore some idea and I'd like the bare metal performance, why would I choose C++ over Rust?

I could choose TypeScript over Rust if I wanted it to be html first or I could choose Go if I wanted it to be clear of the complexity of memory management or I could choose C# if I wanted it to have best interface with windows stuff or I could choose something Erlang VM based for resilience and multithreading.

But what reason might I have to pick C++?

Maybe you don't. If you were to spin up a new project with a coding agent most of the subsequent highlights of the languages you cited might also not matter.
Interfacing with other C++ projects or leveraging existing infrastructure/work you've done.

Rust's package management and lack of stable, high-quality libraries maintained by professional or even just generally known entities are a pretty big problem. For the small number of Rust projects I've attempted, I've tried to make them zero-dependency, and it worked (you just ask agents to implement more libraries) but it added a lot of annoying overhead.

It's also just easier to write high performance code in C/C++. If you'd rather have that than builtin memory safety guarantees or whatever else you want out of Rust, or have a small enough surface for errors/threats that you can just manually spend time validating that your code is safe and secure, C++ is still pretty good IMO. I would generally start with C though, because it makes interop with other languages easier

> Rust's package management and lack of stable, high-quality libraries maintained by professional or even just generally known entities are a pretty big problem.

IMHO, Rusts package management is the opposite of a problem.

And a lot of stable high quality crates exist, such as Tokio, thiserror, chrono, axum, .......

I have nothing but respect and warm feelings for developers who choose to create and maintain software packages and make them available for others.

The problem is that I need to be able to trust my dependencies' provenance. Not just that the developer is good, but that this particular version is good, and that all their dependencies are good and that their versions are good. If there is a security issue in something I use, I need to know that the people responsible for maintaining it have the time and resources to be aware of the problem, quickly patch it, and make the fix available to me; because of that, I also need to regularly check my dependencies' new versions for security fixes and upgrade to them as patches roll out. But I don't have the time to closely review or investigate all of those, so I need to trust that they're handling it without knowing them personally.

Worse, if there is only a single or small group of part-time maintainers handling a package, it would be very easy for a malicious release to be made either unilaterally for financial gain, or unintentionally by some credential hijack (some script pushes a new minor version, they might not notice), or a supply chain hack (eg their build environment got pwned->the software they distribute is not the software they intended to send).

So I prefer to only use 1P packages, dependencies from a well-resourced brand or known figure with something to lose, or dependencies I know very well (and I only have time to know a small number very well). Has nothing to do with the quality of the packages or the developers' skill.

> But I don't have the time to closely review or investigate all of those, so I need to trust that they're handling it without knowing them personally.

so either you pay someone to do the work for you or you hope that someone does it for free?

Or just use fewer, more self-contained dependencies. That's the pattern that's worked well so far.
I think many people coming from the C/C++ world would watch in horror and unease as a "hello world" wgpu project downloads and builds hundreds of dependencies.
If a coding agent is writing code for you, telling it what language to use seems like micromanaging. It might use Rust, it might use C++, it might use both. If it's writing the code, it probably has a better idea than you have for what's appropriate for that code.
Only if you don't intend to maintain, debug, or even understand what the code is doing.

Or at least not without the benefit of more capable coding agents than you used to create it.

And only if the coding agents in question can be trusted to not deliberately or accidentally fail to provide you with critical information ("Now that you mention it, the program does occasionally POST the contents of ~/.aws/credentials to a web server. As this produces no output, I didn't consider it relevant to your question about whether it correctly outputs the string 'hello world'.").