EDIT: Would love to know why people are so angry about that?
So most people will read your view as hypocritical/misinformed.
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.
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.
cppreference is often a bit too technical for its own good :)
But I think there's a broader issue which is that if it took me multiple searches to find a good-enough visual "pitch" for what contracts look like in practice, its champions have not yet won hearts and minds - which brings us to the situation at hand.
- 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++?
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.
Support for contracts is fairly broad and spans numerous organizations.
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.
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.
Spoiler alert: The option described as "the sort of leadership failing that I pray we can avoid" is what ended up happening.
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.
It's just bureaucracy preventing it, not the actual work needed by people.
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.
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.
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).
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.
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.
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".
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.
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.
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.
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!
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.
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 think even if C++ had a periodic ABI break that even a better std::regex spec is fundamentally wrong.
As someone who ships cross-platform I never ever want different platforms to have different implementations for things that are not actually platform specific. Having different implementations of std::string depending on if I’m on windows, Linux, Mac, iOS, Android, PlayStation, Xbox, or Nintendo is a profoundly terrible thing to do.
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.
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.
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.
Phrased differently, contracts are to concepts what assert is to static_assert.
One of the best features to be added to C++ in many years.
C++ contracts are an attempt to bring C asserts into the C++ age. The weakness of C++ contracts is that they are mostly syntactic sugar over C asserts. If you really care about this type of thing, you probably already have a custom C++ assertion framework that is at least as capable if not more.
The promise of C++ contracts is that they can aid formal verification, which would be great. As delivered, it can’t do much more than was already possible, which will inhibit adoption.
The weakness of C++ contracts is that they are mostly syntactic sugar over C asserts.
The sugar is actually one of my issues with them. The evaluation semantics are much more complicated / potentially slower than C asserts because of the sugar, and why you would have to pay those costs isn't obvious at first glance. Lisa Lippincott's excellent talk on the design of contracts [0] is what switched me from a sort of neutral support to disliking it. I think it's a stupid place for the national bodies to draw the line though. std::regex is acceptable, but a nothingburger like contracts tanks the vote?I think the risk is that C++ contracts become an evolutionary dead-end that hang around forever in code bases because they were standardized. It wouldn’t be the first time this has happened.
(IMO the single best improvements over the years have been atomics and maybe variadic templates.)
One thing I give the C++ feature gods credit for is recognizing material deficiencies in systems languages and unapologetically trying to fill those gaps starting with C++11. The addition of atomics, strict variadics, constexpr, lambdas, concepts, lifetime annotations, etc has been transformative for C++.
Say what!?
> the single best improvements over the years have been atomics...
Of course, libatomic and friends have existed for a long time. Real question: Do you feel that the standardisation of atomics within the C++ base library is a material advantage over using libatomic? Also, maybe there are atomic APIs in the C++ base library that are better than libatomic. If so, please kindly share an example or two. I would like to learn more.EDIT
I forgot to give a hat tip to your big upgrade from C++98 to C++23. In some projects, that can require an enormous amount of effort! Can you share a "stories from the trenches" that were difficult in that upgrade?
Atomics could work that way. However many other things cannot - we knew modules were a good idea, but they are a everything on a project must use them before anyone can benefit and so they were forever doomed to not be in widespread use until there is a standard. Even today we see adoption is slow because while there is a standard that works everybody is waiting on some other part to adopt before they can get any benefit. (and those who need to go first see the least benefit), but there are signs that things are moving.
Contracts notionally offer the ability to lift some runtime assertions to compile-time. That is how it was sold. Except they don’t in practice.
Meanwhile, concepts + constexpr if used artfully deliver that in practice, including for many cases that contracts were supposed to solve.
I push all verification to compile-time to the extent possible.
While the C++26 variant of contracts doesn't provide the benefits of its static-analysis-centric ancestor from 2014, and therefore isn't as consequential a feature, it still provides value to some and is absolutely not important enough to be worth killing a standard. Concepts do not provide this value.
In any case, it's simply false that C++26 contracts are unnecessary because we have concepts, yet this claim is the thrust of your initial comment.
Do you have any information as to why they shifted the focus from static analysis to runtime checks? I only remember that it was based on some Microsoft annotation language or something.
Already the compiler is allowed to refuse to compile any code if it would guaranteed fail the contract. The next step is to see how far we can go with that static analysis and what those static analysis tools need to be better. However, this requires people having contracts in fairly widespread use so they can start trying their new ideas to see what happens when they hit the real world.
See my comment here - https://news.ycombinator.com/item?id=50361418
However, i also understand the reasoning behind this C++26 contracts proposition - https://news.ycombinator.com/item?id=50364593
While i understand the rationale here, i can also see the problems it might lead to in the future. Correctness concerns should be an all-or-nothing proposition, you cannot do it piecemeal. Hence whether you want to call it "profiles" or not, i would like a Eiffel/Ada-SPARK like system which gives me complete static compile-time analysis and verification along with separate run-time guarantees.
The contracts committee should go back to the drawing board and come up with a more comprehensive solution.
This is a real chance to finally realize the "Safe C++" dream! Ada did it and so can C++.
Contracts were sold with the idea of aiding compile-time verification, a noble purpose. The combination of concepts + constexpr allows you to do deeper compile-time verification today by other means than contracts can check. It isn’t obvious that this will ever not be the case. This means contracts is relegated to being another flavor of C asserts.
C++26 contracts are arguably unnecessary because we can achieve the same results other ways, sometimes with stronger properties. I’m a proponent of features that clean up the syntax but C++ contracts look like a nod to people that still use legacy C asserts. That’s fine but it also perpetuates an inadequate model of what assertions should be capable of expressing.
People figured out how to do with C++20 better than what contracts promised.
> People figured out how to do with C++20 better than what contracts promised.
What contracts used to promise is irrelevant. The contracts on the table modernized runtime assertions and are irrelevant to concepts, constexpr, and related facilities.
Is the contracts feature more useful than C's assert()?
If you want to argue that we're better off with the old macro, do so directly. Concepts, in this context, amount to irrelevant distraction.
Why would anyone that already ditched C asserts use C++ contracts when it can’t express what the alternatives already can? This isn’t a new problem. People were creating more expressive assertion replacements than contracts offers a decade ago.
C++ contracts are nerfed. It is less expressive and capable than what anyone that cares about these things already uses. So who is expected to use it?
You have not understood the C++26 contracts proposal.
It introduces three new syntax viz. "Pre" and "Post" in function signature declaration and a separate "contract_assert" which you can use anywhere in the code path.
It is the "Pre"/"Post" that is useful here. Since it is part of function signature declaration, a static analyzer can easily make sure that all function calls satisfy the contract else you get warning/error. The compiler on its part can inject appropriate code at the function boundary points to do runtime checking etc.
You cannot do this with assert macros. If you wanted something like this earlier, you would have had to change the compiler to emit modified function prologue/epilogue and build your own contract framework which few people had the capability to do.
You can now see the immediate benefits particularly for standard library (and other) code hardening needs. Many UB circumstances can be easily flagged at compile time without too much complexity.
Finally, note that if you use compile-time switch "ignore" to turn-off everything, only the runtime checks are elided (so you do not lose any performance) but the static analyzer can still catch all possible inconsistencies at compile-time thus giving you the best of both worlds.
How realistic is the "all function calls" part? Maybe I just don't see the bigger picture, but I would expect most function calls arguments to only be known at runtime, which of course makes static analysis not possible?
Obviously "all function calls" phrase cannot be absolute, but most can be caught with the analyzer giving one of proved/disproved/unknown result. The reason all cannot be caught is because pre/post are logical predicates on sets of values and are not part of the typing system.
To understand that, you have to know how a static analyzer works and specifically two of its functions, "Data Flow Analysis" and "Symbolic Execution".
It is Symbolic Execution that does static checking without the need for the actual runtime values to be known. It basically "executes" the code mathematically, building logical predicates over "sets of values" (indicated by the type of the variable) and thence trying to prove/disprove the formula using a solver. Note that the program is being "run" abstractly in the mathematical world using quantifiers just like you do in a mathematical proof.
If you know Hoare triples, and Dijkstra's WP-Calculus you know how to do this mechanically.
So the analyzer does two things; a) in the function itself it assumes pre is true and tries to prove post and b) at the call site it makes sure the paths leading up to the invocation satisfy the pre/post args/result needs thus chaining everything through the codebase. Both are done using symbolic execution. If it cannot prove/disprove the assertions, it remains silent (i.e. "unknown" result above) and leaves it to runtime checks to catch the violations.
Some resources:
1) How Static Analysis works - https://pvs-studio.com/en/blog/posts/1048/
2) A Gentle Introduction to Symbolic Execution for Software Security - https://can-ozkan.medium.com/a-gentle-introduction-to-symbol...
3) Scaling Symbolic Execution to Large Software Systems - https://arxiv.org/abs/2408.01909
> 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?This also sounds pretentious ...
The only other legitimate choice for writing software at the time would have been ADA, which for some reason never took off despite being purpose build for the application. Of that time, C++ was the new hotness, it was popular, it was solving architectural problems, and it was performant, unlike say Java.
It’s fairly naive to say “I’d never use C++”. The C++ programmers of the time would have looked at Fortran or COBOL with the same level of disdain. We are lucky to live in a time of better options, and the impending post code future.
Ada makes a lot more sense for this work than C++ did twenty years ago.
And then the industry swapped to C++. This was not a DoD mandate, this was companies like boeing trying to pay their engineers 1/3 to 1/2 less by paying for C++ devs (starting salary for ada devs was 90-140k, starting salary for c++ devs was 60-180k according to exit statistics). They of course eventually learned that good C++ devs are actually more expensive than their old Ada ones. Not that they bothered to hire good c++ devs.
Until Ada Core offered GNAT to the community, there were no affordable compilers.
Yet, there is still enough business to keep 6 compiler vendors selling them.
What do you mean?
In today's terms, that's like vibecoding a Mars mission vehicle just because it's "cool".
(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)
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!
Boeing and other defense contractors dropped it because C++ programmers were cheaper on paper (not realizing/caring that good C++ engineers were more expensive).
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
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 (defensive programming, basically an inline test), and wrapper/error handling types to do what you might want contracts to do:
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;
}
(function impl is AI, 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, C++ basically felt like a different language. People say that the C++ standards committee and language designers 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, a lot of what they want to add is already "solved" by third party tooling, but because for whatever reason they don't use those 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 the 3P tools that 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/ one of many third party ways to make C++ less insane
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).
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!
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.
If they can't, then it is IMO a mistake for the language to make contracts declarative (like types), or to think of the static checks as anything more than something extra on top of what is actually a runtime check. And if they can, then why are they not just types?
Bad idea to assume "someone will write static analyzers", and use that to justify a language feature capable of expressing much more complex logic than any static analyzer would be capable of handling.
See also my comments here - https://news.ycombinator.com/item?id=50365641 and https://news.ycombinator.com/item?id=50375318 (this one explains how static analysis works which is the confusion i see above).
The idea of a "proof" which is what Symbolic Execution by a Static Analyzer does is different on both sides of the above isomorphism. You cannot mix them indiscriminately. This is because C++ does not have a typing theory (in the sense of lambda calculus derivatives) but simply maps types to sets. Hence one cannot do "Type-Driven Design" natively like a lambda calculus-based language even though you can do aspects of it via explicit programming techniques (eg. see "Functional Programming in C++ by Ivan Cukic").
That is the reason i suspect contracts in C++ moved away from the original focus on static analysis to managed runtime checks + some static analysis. C++26 contracts are firmly in the Set Theory/Predicate Calculus camp and are not integrated into the Type System.
We need an augmentation of the C++ type system and then a narrowing so we can end up with something like Ada-SPARK (call it "Safe C++"/"Profiles"/whatever).
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.
There were no "dirty tricks". The C++ standards committee works by a vaguely defined "consensus", which requires more than "the majority rules". Contracts got added to the C++26 draft. Then there was consensus that Contracts needed to be fixed, but they could never get consensus on any particular fix. So they cruised along relatively unchanged.
In the end, the only way to NOT accept a marginal Contracts feature was to vote down the full language spec. Now they'll regroup and decide how to proceed.
Stroustrup is 75 years old. This is not only hard to believe because of his age, but also because it requires that people who oppose his views somehow have distinct sleeping patterns from ones who agree with his views. Weird, man.
Not weird if they're mostly from different continents.
When I saw him a year or so ago he said he wasn't happy with how things were going, but never alluded to a coup. But it's his language, so good for him.
It most definitely is not and hasn't been in decades.
A major problem is that some people still put his views on a pedestal, acting like he has a clean track record with his ideas, which he definitely has not - no language designer has ...
...He has the power to do this? And for which elections, exactly? The main go/no-go votes are the ones at the big meetings and I'd imagine there's not a lot of room for scheduling shenanigans there.
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++ principles. They have been published since at least 2017. Contracts aren't new, 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.
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 grounded on petty politics, and dismissing yet again a failure to gather consensus as personal attacks and a political issue.
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.
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.
Stroustrup's objection of subversion of, and politicization of the "consensus" process seems pretty darned reasonable to me.
And having two major compiler implementers (Clang and Microsoft) among those opposed to the proposal seems like a very poor sort of consensus to me.
The decision to defer how contracts on virtual methods work until C++29 strikes me as particularly horrifying, and renders the feature completely unusable precisely at the point where it most needed (PIMPL classes where public methods are pure virtual, with implementation provided in a private derived class).
And reminds me of c++20 coroutines, for which we are still awaiting a usable implementation. I made the mistake of actually writing a wrapper library for c++ coroutines. A great feature, but only heroically usable in its c++20 incarnation. (I actually did use it in project, but was left wondering why anyone would actually release THAT feature without a supporting class library). Implementation details were shocking, and awful, and insufficiently specified. And I would be completely amazed if my wrapper library continues to work with C++26.
God willing, C++26 will provide an implementation that allows us to sanely use coroutines in message pumps and thread pools soon (such a great feature!), if the standards committee, God Willing, takes the right and good and sensible path of removing contracts from C++26 so that we can get the structured concurrency library.
All in all, I can't help wondering whether the C++ standard doesn't need "Experimental Features" like Java has. It's certainly interesting to see how The Who Must Not Be Named (Oracle) uses experimental features, some of which have existed in experimental status across four or five Java releases. C++20 coroutines and contracts would have been perfect candidates for "experimental C++ features", that can be tested and hardened and have breaking ABI changes made as necessary and appropriate.
> welcome a contracts design that is simple, and “marketed” as just a debug aid
The operative word would be "simple". It's hard to imagine that the feature would require 56 (!!) pages of specifications if the constness rule were omitted. Who the heck ordered that!!??
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.
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.
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.
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.
At a broad view, we get to a place where there's no "bug" when "what happens on overflow" is what the program(mer) wants.
All I said is that you can remove undefined behavior from signed overflow without having to introduce checks to every arithmetic operation and without having to specify any particular behavior or outcome. The technical term for this is "unspecified behavior" and the consequence of making overflow unspecified behavior is that the consequences of overflow, while still unspecified, must be bounded in space and time, unlike undefined behavior whose consequences are not required to be bounded in either space or time.
You can define a behaviour today that they'll all get, but you can't define a behaviour that matches what each programmer needed when they wrote their operation. Some of them can wrap safely. Some of them would need to saturate. Others would need it to abort.
The problem isn't that the behaviour is undefined per se, it's that you can't tell afterwards which potential behaviour the programmer needs, and choosing one behaviour e.g. wrap will break everyone who actually needed saturating, or trapping, etc.
Contrary to Contracts, which at least managed to get consensus in WG21, I very much doubt that Profiles will get consensus.
I pretty much do all my low level vibe coding in Rust. Is C++ still relevant? What prevents Rust from completely supplanting it?
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.
Personally, I think it is still relevant. Many people thought Kotlin could overtake Java, Java reinvented itself with new initiatives/features and was saved from becoming irrelevant.
Rust also has the LLM advantage which is where I think the "if it compiles it works" nature of Rust is easier for manual changes and maintenance when needed.
Rust can literally do anything programmatically. Idk why you think it cannot do something.
If you mean things that formally create a data race, then C++ cannot do that either.
Even in their case. Rust depends on LLVM which is wriiten in C++. Go needs libc on some platforms.
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.
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++.
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...
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.
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.
Could you expand on what specific safety features C++ has that Rust doesn't?
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.
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.
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.
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.
And we have no idea what AI systems will be doing in 2027.
>
> 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.
SIMD on different silicon is incompatible at layers of abstraction far above the codegen manipulation a compiler can do.
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.
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.
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.
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.
Other targets and languages have portable SIMD targets that are a bit more advanced, but I think WASMs SIMD design is the best for generically getting your feet wet.
ISPC doesn't a pretty good job of it: https://ispc.github.io/
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.
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).
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.
std::simd is unfortunately very limited.
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 they say this is the first case where a DIS failed during the standardization consensus process. Why is that?
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?
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.
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.
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.
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?
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.
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.
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.
> 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.
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.
It's implemented in GCC mainline, it's implemented on a branch of Clang. Considering MSVC: at this point in time I'm not convinced it it a question of implementability, but of will: https://cppstat.org/de/?tags=cpp26&type=lang
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.
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?
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.
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.
That's my opinion as well. It's a smear campaign lashing back at people who dared to point out flaws.
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?
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...
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.
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.
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.
> 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.
You don't have to agree, but this is how I see it.
That is explicitly not what I'm claiming. You seem to think that I think "memory safety" is equivalent to "safety", which is what I've repeatedly told you is not what I'm saying. That's conflation. It's not clear why you'd expect me to read more details you give after repeatedly ignoring what I'm saying and putting words in my mouth that I'm not saying, so I have to assume at this point you're posturing for other readers rather than actually trying to communicate with me in any reasonable way.
But maybe I am still not getting your point correctly.
Yes, there can be compiler bugs that cause unsafety in safe Rust code, and it's possible to have unsafety in dependencies that leads to issues in code that otherwise looks safe, but this can happen in C++ as well. My point is that the risk of having memory unsafety from bugs that you write in your own Rust code is effectively zero if you don't ever use the unsafe keyword, and this is how most Rust code is written in practice. Most C++ code is not written in a way that produces anywhere close to this level of confidence because the language fundamentally does not support anything like that. I don't think that contracts would fundamentally change this.
On their own, no. What contracts provide are annotations for how the programmer expects the code to behave, which can be verified by model checkers or automatic theorem provers. These can already verify memory safety properties; borrow checking only does a subset of what a model checker can do. To scale model checking up so it can work on a large codebase, compositional verification is required. Contracts enable compositional verification, which in turn allows developers to write code safer than what is possible with vanilla Rust or Java.
I do this today with C. The model checked C I write is safer than software written in Rust without a model checker. It is memory safe, and it is verified to work within the specification that I have designed. As far as the specification is correct, it is correct.
We can't rewrite the world in Rust. There are many billions of lines of code in C and C++ that aren't going away. Instead, we need to find ways of making this code safe with as little change to it as possible.
In practice, we also still see memory safety issues also in Rust code exactly because people use "unsafe" or have a dependency that does. I also see that practical impact of memory safety issues in well-maintained C/C++ code is almost zero on my personal security (rare, often mitigated or extremely difficult to exploit). And after the LLM wave of issues is processed, this will be even less a problem. I am far more scared about supply chain issues (and I bring this up as comparison for proper risk assessment, not to move away the discussion from memory safety).
Then, theoretically, one could also make sure C/C++ have no memory safety issues. (And I have done this myself in toy programs and industry also for larger projects, so this is not even purely theory.) The languages does not fully support this yet, yes, but why does this matter so much? The language / compiler / good coding standards still support reducing memory safety issues to low levels - which is relevant, because outside of theoretical scenarios, this is what Rust also achieves in practice (and not perfection in getting rid of memory safety issues).
And then now in this thread, this argument that in C/C++ it is more difficult to achieve perfect memory safety was even used as argument against a feature that would be a step towards making this easier. This I find completely misguided.
(I am not talking about compilers bugs).
Contracts are annotations, much like types are. What makes contracts powerful is the tool that examines this annotation, as is the case with types. A type checker, such as an H-M type checker, can only perform limited checks. It's possible to use a dependent type checker with dependent types, but this is undecidable, and it requires a proof assistant and human guided tactics to resolve. In practice, this is expensive, and when automation such as LLMs are used, one currently gets tactic soup that is difficult to understand, which defeats the purpose.
A model checker, such as CBMC or ESBMC, can work with contracts to verify specification that would be difficult to verify without contracts. Model checkers can already verify memory safety and even the absence of memory leaks across an entire program. However, model checking grows exponentially expensive as we add more code to be verified. Contracts give us the ability to perform compositional verification, which allows us to verify codebases into the millions of lines of code or larger by breaking down this verification into many small model checks, stitching these together with contracts and invariants. Contracts and invariants complement type checking and significantly extend it. It's possible to use contracts and invariants to add these checks to an untyped language or a minimally typed language such as C. If my precondition includes the data invariant, "property_valid_widget(x)", then effectively, this also type checks x. This works even if I've completely erased the type and later recast it.
The "real world" doesn't currently have a solution for reducing general software safety issues -- which goes far beyond memory safety -- other than formal methods. Practical and efficient ways to formally verify software is within our reach, and is already being done with other languages. I do this today with C / CBMC using contracts and invariants. I get memory safety, specification safety, and a guarantee of no memory leaks. This can also be done with C++, Rust, Java, and other languages using similar techniques. While it is true that Rust and Java both have basic memory safety in place, they also both can harbor vulnerabilities that could be resolved with function contracts and model checking.
Contracts are more than useful; they give visibility of developer intent to model checkers and similar tools. This visibility makes software significantly safer than borrow checking or type checking can alone.
Can you tell us more how you use cbmc with macros? I am also exploring this.
I also wonder what feature from C++ you miss in C?
https://www.bsdcan.org/2026/timetable/timetable-Model-Checki...
That link has the slides and some example code. There's also a live stream on YouTube.
Regarding features I miss from C++, I like the concept of generics. I don't like the implementation in C++. I also find C's _Generic facility to be limited, especially when building containers that perform hygienic type erasure. This feature isn't enough for me to go back to C++ on its own, but it is something I'm exploring in a new language I'm writing.
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?
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.
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 where you read that but it is a blatant lie - easily disproven by the way: N5046 which is pretty close to the C++26 DIS has 2668 pages. P2900R14 has a total of 114 pages, of which ~56 pages are dedicated to proposed wording.
Wording is presented as a diff to the working draft and contains extensive copies of the existing text that is either amended, modified or removed. (Aka: there are no 56 pages of wording).
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.
what is it though? vcpkgs/decentralized repositories?
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.
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.
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++?
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
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, .......
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.
so either you pay someone to do the work for you or you hope that someone does it for free?
But I wouldn't have to do that as much in languages with larger standard libraries or more established libraries/tools/ecosystems (eg abseil in C++, numpy and tensorflow in python).
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'.").
Not new features necessarily, but fixes or backports that fix major flaws.
It can also complement old standards. If a C++23 feature can be supported in C++98 or C++11, it should go to that standard with an update.
The whole design committee procedure around these languages feels like a bureaucratic nightmare, again compared to other languages, especially Rust.
I also think since compiler infrastructure has improved so much, and everything is open source now ... so idk if it matters as much anymore.
The world basically runs on C.
The main driver is a group of people willing to submit the necessary documents to ISO (or national bodies like ANSI or DIN or even IEEE, and then ISO may also adopt existing standards as theirs).
COBOL, FORTRAN and Pascal are all ISO Standards [1,2,3].
[1] https://www.iso.org/standard/74527.html
https://en.wikipedia.org/wiki/Category:Programming_languages...
2) C++ it's a monster which should died long ago.
3) Go should take the role of small tools such as some services and mail/IRC clients, especially for CLI/TUI. Or stuff like urlview. Rust the big ones (media encoding, PDF libraries, browsers...)
4) Unreal 6 will ditch c++. Good riddance.
I'm not arguing one way or the other (for C++ or Rust) but it's certainly worth considering.
I believe AI is the final nail in the coffin for C/C++ although it'll be a long, slow decline. C++'s backward compatibility with C cannot be resolved and you can never really be sure about memory ownership let alone safety. C++ in particularly is simply too complex. I didn't trust people to write correct C++ before AI without severe restrictions (eg Google's guidelines). I certainly don't now.
The problem appears to be that they didn't have the majority needed to reject it at any of the previous points in the process, so we've now ended up with a stalemate where neither the Ayes nor the Nays can actually execute their position effectively
It was said in the article about the process.
But to me this is relevant to the state of the language itself.
You can fix every problem in language design with more language features, except "too many language features". Most people on the committee even seem to intellectually understand this, but their preferred time to stop adding new major features is "once my pet feature is in".
And to harp on the safety thing a bit: In the absence of an actually safe subset of C++, additional language complexity is also a safety problem. "best effort" safety like the stuff C++ is pursuing at the moment still relies on you knowing exactly what your code does, which is hindered by complexity.
Here's an example for contracts. Say you have the following declaration:
void foo(int* p)
pre (p != nullptr)
pre (*p >= 0);
What happens if you pass a nullptr? You'd guess that it either raises a contract violation or silently ignores it, right? Yes, those are two possibilities, in the "enforce" and "ignore" modes respectively. But there's also an "observe" mode, where the preconditions are checked at runtime and violations reported but then execution resumes normally. Can you see the problem? Passing a nullptr causes evaluation of the second precondition to deref it, so we get UB from the contracts themselves before we ever hit the function body (which might have its own, classic nullptr checks, who knows). This is a completely new class of footgun that you never had with assertions (they are always either enforced or ignored).This half-baked contracts proposal has been systematically cut out of the draft since at least 2020.
I mean, how long does it take to fix it? Perhaps it's unsalvageable?
Their proponents seem to be more interested in playing political games than to fix the mess they presented. Apparently they don't mind sabotaging the C++ standardization process to get their way.
Internal use only is helpful but doesn't get the feature used, and too often leaves things not useful for a toolchain but useful elsewhere out.
they can just simply use Zig or Rust no ??
What kind of design process is this
In reality WG21 could just decide to start work on C++29 based on the failed C++26 draft (or the current working draft has already incorporated some C++29 changes)...
It is not. This is a lame attempt scaremongering, to try to inflate the consequences of contract proponents not getting their way. It's like sore losers threatening to take the ball home to prevent everyone from continuing to play the game, and claiming that taking the ball home is how games are normally played.
In practice, the standard passes the moment the sticking points are ironed out. This likely means cutting out contracts yet again, which has been done every single release since at least C++20.
Why yes, because the C++20 was so poorly thought through that in the July 2019 WG21 meeting the design was deemed irremediably broken, and consequently the committee made the unprecedented decision to just disband the group and start over by forming a new one. This happened so close to the kickoff that contracts were right there excluded from C++23.
And after all these years, the proposal remains broken.
1. Start a new version (lets call it v2) with clean slate.
2. Retain the re-usability of v1 code in v2 in the same manner as FFI (i.e v2 code will wrap v1 code). But it will be much more smoother as it will be designed in v1 in mind.
3. Leverage AI to make the transition to write this v2 -> v1 code.
Also from a procedural perspective the technical committee was wrong. It is supposed to send drafts to DIS when there is consensus. They did it based an a plenary vote. That is not what consensus is, and also not how ISO defines it. Consensus is the absence of sustained opposition. Contracts never had consensus, DIS simply responded to that procedural snafu.
The proponents of Contracts can then polish their proposal and try again.
It's just another syntax for 'if' and sentence in spec that they wish it for "program bugs".
Some languages have pre/post conditions and use it for wrapping function call with pre/post functions that do something. Useful in Emacs when you can tweak your config a bit. But do not crash application.
Some languages have condition that limit when function/method is called eg. for x > 5 is called one function and for rest numbers another function. Useful, cost runtime check but do not crash app. eg. your F35 in the middle of the air...
And from all possible things they choose to do plain asserts crash...