8 ms·
I am somewhat dismayed that contracts were accepted. It feels like piling on ever more complexity to a language which has already surpassed its complexity budge
by suby 6mo ago
I am somewhat dismayed that contracts were accepted. It feels like piling on ever more complexity to a language which has already surpassed its complexity budget, and given that the feature comes with its own set of footguns I'm not sure that it is justified.
Here's a quote from Bjarne,
> So go back about one year, and we could vote about it before it got into the standard, and some of us voted no. Now we have a much harder problem. This is part of the standard proposal. Do we vote against the standard because there is a feature we think is bad? Because I think this one is bad. And that is a much harder problem. People vote yes because they think: "Oh we are getting a lot of good things out of this.", and they are right. We are also getting a lot of complexity and a lot of bad things. And this proposal, in my opinion is bloated committee design and also incomplete.
- addaon 6mo agoI can’t speak to the C++ contract design — it’s possible bad choices were made. But contracts in general are absolutely exactly what C++ needs for the next step of its evolution. Programming languages used for correct-by-design software (Ada, C++, Rust) need to enable deep integration with proof assistants to allow showing arbitrary properties statically instead of via testing, and contracts are /the/ key part of that — see e.g. Ada Spark.
- StilesCrisis 6mo agoRight, I think the tension here is that we would like contracts to exist in the language, but the current design isn't what it needs to be, and once it's standardized, it's extremely hard to fix.
- bluGill 6mo agoThe people who did contracts are aware of ada/spark and some have experience using it. Only time will tell if it works in c++ but they at least did all they could to give it a chance. Note that this is not the end of contrats. This is a minimun viable start that they intend to add to but the missing parts are more complex.
- dislikedopinion 6mo agoMight be the case that Ada folks successfully got a bad version of contracts not amenable for compile-time checking into C++, to undermine the competition. Time might tell.
- steveklabnik 6mo agoThis is some pretty major conspiracy thinking, and would need some serious evidence. Do you have any?
- dislikedopinion 6mo ago[flagged]
- steveklabnik 6mo agoOkay, on one hand, I'm very curious, but on the other hand, not really on topic for this forum. So I'll just leave a "wut".
- stackghost 6mo agoI strongly doubt that C++ is what's standing in the way of Ada being popular.
- dislikedopinion 6mo agoAda used to be mandated in the US defense industry, but lots of developers and companies preferred C++ and other languages, and for a variety of reasons, the mandate ended, and Ada faded from the spotlight.
- stackghost 6mo ago>the mandate ended, and Ada faded from the spotlight Exactly. People stopped using Ada as soon as they were no longer forced to use it. In other words on its own merits people don't choose it.
- derriz 6mo agoC++ is the last language I'd add to any list of languages used for correct-by-design - it's underspecified in terms of semantics with huge areas of UB and IB. Given its vast complexity - at every level from the pre-processor to template meta-programming and concepts, I simply can't imagine any formal denotational definition of the language ever being developed. And without a formal semantics for the language, you cannot even start to think about proof of correctness.
- addaon 6mo agoAs with Spark, proving properties over a subset of the language is sufficient. Code is written to be verified; we won’t be verifying interesting properties of large chunks of legacy code in my career span. The C (near-) subset of C++ is (modulo standard libraries) a starting point for this; just adding on templates for type system power (and not for other exotic uses) goes a long way.
- extrabajs 6mo agoI don’t think this is a good comparison. Ada (on which Spark is based) has every safety feature and guardrail under the sun, while C++ (or C) has nothing.
- uecker 6mo agoThere is a lot of tooling for C though, just not in mainstream compilers.
- jesse__ 6mo ago> The C (near-) subset of C++ is (modulo standard libraries) a starting point for this; just adding on templates for type system power (and not for other exotic uses) goes a long way. In my experience, this is absolutely true. I wrote my own metaprogramming frontend for C and that's basically all you need. At this point, I consider the metaprogramming facilities of a language it's most important feature, by far. Everything else is pretty much superfluous by comparison
- steveklabnik 6mo agoThe devil is in the details, because standardization work is all about details. From my outside vantage point, there seems to be a few different camps about what is desired for contracts to even be. The conflict between those groups is why this feature has been contentious for... a decade now? Some of the pushback against this form of contracts is from people who desire contracts, but don't think that this design is the one that they want.
- quotemstr 6mo agoBut why? You can do everything contracts do in your own code, yes? Why make it a language feature? I'm not against growing the language, but I don't see the necessity of this specific feature having new syntax.
- jandrewrogers 6mo agoDYI contracts don't compose when mixing code using different DYI implementations. Some aspects of contracts have global semantics.
- deleted 6mo ago[deleted]
- jevndev 6mo agoThe common argument for a language feature is for standardization of how you express invariants and pre/post conditions so that tools (mostly static tooling and optimizers) can be designed around them. But like modules and concepts the committee has opted for staggered implementation. What we have now is effectively syntax sugar over what could already be done with asserts, well designed types and exceptions.
- addaon 6mo agoContracts are about specifying static properties of the system, not dynamic properties. Features like assert /check/ (if enabled) static properties, at runtime. static_assert comes closer, but it’s still an awkward way of expressing Hoare triples; and the main property I’m looking for is the ability to easily extract and consider Hoare triples from build-time tooling. There are hacky ways to do this today, but they’re not unique hacky ways, so they don’t compose across different tools and across code written to different hacks.
- spacechild1 6mo agoPre- and postconditions are actually part of the function signature, i.e. they are visible to the caller. For example, static analyzers could detect contract violations just by looking at the callsite, without needing access to the actual function implementation. The pre- and postconditions can also be shown in IDE tooltips. You can't do this with your own contracts implementation. Finally, it certainly helps to have a standardized mechanisms instead of everyone rolling their own, especially with multiple libraries.
- wpollock 6mo ago> Programming languages used for correct-by-design software (Ada, C++, Rust) ... A shoutout to Eiffel, the first "modern" (circa 1985) language to incorporate Design by Contract. Well done Bertrand Meyer!
- kajaktum 6mo agoC++ needs to give itself up and make way for other, newer, modern, language that have far, far fewer baggage. It should be working with other language to provide tools for interop and migration. C++ will never, ever be modern and comprehensible because of 1 and 1 reason alone: backward compatibility. It does not matter what version of C++ you are using, you are still using C with classes.
- Guvante 6mo agoWhy should C++ stop improving? Other languages don't need C++ to die to beat it.
- ratmeadow 6mo agoHalf-serious reason: because with each C++ version, we seem to get less and less what we want and more and more inefficiency. In terms of language design and compiler implementation. Are we even at feature-completeness for C++20 on major compilers yet? (In an actually usable bug-free way, not an on-paper "completion".)
- jandrewrogers 6mo agoThe compiler design is definitely becoming more complicated but the language design has become progressively more efficient and nicer to use. I’ve been using C++20 for a long time in production; it has been problem-free for years at this point. It is not strictly complete, e.g. modules still aren’t usable, but you don’t need to wait for that to use it. Even C++23 is largely usable at this point, though there are still gaps for some features.
- yolina 6mo agogcc seems to have full C++20, almost everything in 23 and and implemented reflection for 26 which is probably the only thing anyone cares about in 26. https://en.cppreference.com/w/cpp/compiler_support.html https://en.cppreference.com/w/cpp/compiler_support.html Funny how gcc seems to be the top dog now, what happened to clang? Thought their codebase was supposed to be easier and more pleasant to work with? Or maybe just more hardcore compiler devs work on gcc?
- ozgrakkurt 6mo agoI don’t understand this “next evolution” approach to language design. It should be done at some point. People can always develop languages with more or less things but piling more things on is just not that useful. It sounds cool in the minds of people that are designing these things but it is just not that useful. Rust is in the same situation of adding endless crap that is just not that useful. Specifically about this feature, people can just use asserts. Piling things onto the type system of C++ is never going to be that useful since it is not designed to be a type system like Rust's type system. Any improvement gained is not worth piling on more things. Feels like people that push stuff do it because "it is just what they do".
- jandrewrogers 6mo agoMany of the recent C++ standards have been focused on expanding and cleaning up its powerful compile-time and metaprogramming capabilities, which it initially inherited by accident decades ago. It is difficult to overstate just how important these features are for high-performance and high-reliability systems software. These features greatly expand the kinds of safety guarantees that are possible to automate and the performance optimizations that are practical. Without it, software is much more brittle. This isn’t an academic exercise; it greatly reduces the amount of code and greatly increases safety. The performance benefits are nice but that is more on the margin. One of the biggest knocks against Rust as a systems programming language is that it has weak compile-time and metaprogramming capabilities compared to Zig and C++.
- jesse__ 6mo ago> powerful compile-time and metaprogramming capabilities While I agree that, generally, compile time metaprogramming is a tremendously powerful tool, the C++ template metaprogramming implementation is hilariously bad. Why, for example, is printing the source-code text of an enum value so goddamn hard? Why can I not just loop over the members of a class? How would I generate debug vis or serialization code with a normal-ish looking function call (spoiler, you can't, see cap'n proto, protobuf, flatbuffers, any automated dearimgui generator) These things are incredibly basic and C++ just completely shits all over itself when you try to do them with templates
- Sharlin 6mo agoProblem is contracts mean different things to different people, and that leads standard contracts support being a compromise that makes nobody happy. To some people contracts are something checked at runtime in debug mode and ignored in release mode. To others they’re something rigorous enough to be usable in formal verification. But the latter essentially requires a completely new C++ dialect for writing contract assertions that has no UB, no side effects, and so on. And that’s still not enough as long as C++ itself is completely underspecified.
- bluGill 6mo agoThis contacts was intended to be a minimum viable product that does a little for a few people, but more importantly provides a framework that the people who want everything else can start building off of.
- raincole 6mo agoI mean... it's C++. The complexity budget is like the US government's debt ceiling.
- Maxatar 6mo agoWithout a significant amount of needed context that quote just sounds like some awkward rambling. Also almost every feature added to C++ adds a great deal of complexity, everything from modules, concepts, ranges, coroutines... I mean it's been 6 years since these have been standardized and all the main compilers still have major issues in terms of bugs and quality of implementation issues. I can hardly think of any major feature added to the language that didn't introduce a great deal of footguns, unintended consequences, significant compilation performance issues... to single out contracts is unusual to say the least.
- jibal 6mo agoIt doesn't sound that way to me, but there's a lot of context at https://youtu.be/tzXu5KZGMJk?t=3160 https://youtu.be/tzXu5KZGMJk?t=3160
- jandrewrogers 6mo agoC++ contracts standardizes what people already do in C++. Where is the complexity in that? It removes the need to write your own implementation because the language provides a standard interoperable one. An argument can be made that C++26 features like reflection add complexity but I don't follow that argument for contracts.
- ghosty141 6mo agoThe quote of Bjarne is a bit out of context. It was made after an hour long talk about the pitfalls and problems of contracts in c++26: https://youtu.be/tzXu5KZGMJk https://youtu.be/tzXu5KZGMJk This should also clarify the complexity issue.
- seertaak 6mo agoCan you share what aspects of the design you (and Stroustroup) aren't happy with? Stroustroup has a tendency of being proven right, with 1-3 decade lag.
- ghighi7878 6mo agoWell thats not always true. Initializer list is a glaring example. So are integer promotion some other things like
- seertaak 6mo agoInteger promotion? - Stroustroup pleads C source compat else stillborn. Initializes lists suck mainly because of C source compat constraints, too. In fact, most things that suck in C++ came from B via C.
- tialaramex 6mo agoCertainly we can say that Bjarne will insist he was right decades later. We can't necessarily guess - at the time - what it is he will have "always" believed decades later though.
- seertaak 6mo agoYou made me laugh!...Bjarne indeed can't be accused of being a modest man. And by some accounts, he's quite a political animal. But in fairness, when was D&E first published? Argued for auto there, long before their acceptance. Argued for implicit template instantiation - thank god the "everything-must-be-explicit" curmudgeons were vanquished there, too. He's got a pretty good batting average - certainly better than Herb Sutter.
- devnullbrain 6mo agoSource of quote: https://youtu.be/tzXu5KZGMJk?t=3160 https://youtu.be/tzXu5KZGMJk?t=3160
- Waterluvian 6mo agoHas any project ever tried to quantify a “complexity budget” and stick to it? I’m fascinated by the concept of deciding how much complexity (to a human) a feature has. And then the political process of deciding what to remove when everyone agrees something new needs to be accepted.
- ghighi7878 6mo agoJust because Bjarne thinks the feature is bad doesnt mean it is bad. He can be wrong. The point is, most peoppe disagree with him, and so a lot of peoppe do think it is good.
- gmueckl 6mo agoThere have been several talks about contracts and the somewhat hidden complexities in them. C++ contracts are not like what you'd initally expect. Compiler switches can totally alter how contracts behave from getting omitted to reporting failures to aborting the program. There is also an optional global callback for when a contract check fails. Different TUs can be compiled with different settings for the contract behavior. But can they be binary compatible? In general, no. If a function is declared in-line in a header, the comoiler may have generated two different versions with different contract behaviors, which violates ODR. What happens if the contract check calls a helper function that throws an exception? The whole things is really, really complex and I don't assume that I understand it properly. But I can see that there are some valid concerns against the feature as standardized and that makes me side with the opposition here: this was not baked enough yet
- nulltrace 6mo agoCoroutines went through the same cycle. Standardized in C++20, and I still hit compiler-specific differences in how symmetric transfer gets lowered.
- btilly 6mo agoThat sounds like the worst kind of misfeature. It sounds like it should solve your problem. At first it seems to work. Then you keep on finding the footguns after it is too late to change the design.
- bluGill 6mo agoContracts are designed as a minimum thing that can work. The different groups who want different - conflicting - things out of contracts now have a common place and syntax examples to start adding what they want without coming up with something that either breaks someone else, or worse each group doing things in a non-uniform way thus causing foot guns. Contracts as they are today won't solve every problem. However they can expand over time to solve more problems. (or at least that is the hope, time will tell - there is already a lot of discussion on what the others should be)
- DenisM 6mo ago>to a language which has already surpassed its complexity budget I've been thinking that way for many years now, but clearly I've been wrong. Perhaps C++ is the one language to which the issue of excess complexity does not apply.
- selfmodruntime 6mo agoIn essence, a standard committee thinks like bureaucrats. They have little to no incentive to get rid of cruft and only piling on new stuff is rewarded.
- WalterBright 6mo agoIn D, we are implementing editions so features that didn't prove effective can be removed.
- selfmodruntime 6mo agoI am sadly not in the position to use D at work, but I appreciate your work!
- bluGill 6mo agoI don't know what you mean by effective - I can come up with several different/conflicting definitions in this context. I think what you meant to say is popular. If a feature is popular it doesn't matter how bad it turns out in hindsight: you can't remove it without breaking too much code (you can slowly deprecate it over time, I'm not sure how you handle deprecation in D, so perhaps that is what editions give you). However if a great feature turns out not to be used you can remove it (presumably to replace it with a better version that you hope people will use this time, possibly reusing the old syntax in a slightly incompatible way)
- poppadom1982 6mo agoYeah dude but you've really marketed D poorly. I remember looking at D what must be 15 years back or so? And I loved the language and was blown away by its beauty and cool features. But having no FOSS compiler and the looming threat of someone claiming a patent (back then it was unclear that Mono/C# was "legal" and even Java hung in the balance) was too scary for me to touch it. Now I'm old and I believe D has missed its opportunity. Kinda sad.
- zzzoom 6mo agoThat's a genius idea, keep adding broken stuff into the standard until there's no choice but to break compatibility to fix it.
- karmakurtisaani 6mo agoNo no no, you add new stuff that will totally fix those problems!
- WalterBright 6mo agoI implemented Contracts in the C++ language in the early 90's as an extension. Nobody wanted it. https://www.digitalmars.com/ctg/contract.html https://www.digitalmars.com/ctg/contract.html
- ChrisGreenHeur 6mo agoit could be possible that llms can mak great use of them
- sidkshatriya 6mo ago> it could be possible that llms can mak great use of them This is actually a good point. Yes, LLMs have saturated the conversation everywhere but contracts help clarify the pre-post conditions of methods well. I don't know how good the implementation in C++ will be but LLMs should be able to really exploit them well.
- quuxplusone 6mo agoThe problem with that is that C++26 Contracts are just glorified asserts. They trigger at runtime, not compile time. So if your LLM-generated code would have worked 99% of the time and then crashed in the field... well, now it will work 99% of the time and (if you're lucky) call the contract-violation handler in the field. Arguably that's better (more predictable misbehavior) than the status quo. But it's not remotely going to fix the problem with LLM-generated code, which is that you can't trust it to behave correctly in the corner cases. Contracts can't make the code magically behave better; all they can do is make it misbehave better.
- celrod 6mo agoIn my experience, llms don't reason well about expected states, contracts, invariants, etc. Partly because that don't have long term memory and are often forced to reason about code in isolation. Maybe this means all invariants should go into AGENTS.md/CLAUDE.md files, or into doc strings so a new human reader will quickly understand assumptions. Regardless, I think a habit of putting contracts to make pre- and post-conditions clear could help an AI reason about code. Maybe instead of suggesting a patch to cover up a symptom, an AI may reason that a post-condition somewhere was violated, and will dig towards the root cause. This applies just as well to asserts, too. Contracts/asserts actually need to be added to tell a reader something.
- raverbashing 6mo agoGeez if Bjarne thinks it's > bloated committee design and also incomplete That's truly in that backdoor alley catching fire
- armchairhacker 6mo agoI wonder if C++ already has so much complexity, that it would actually be a good idea to ignore feature creep, and implement any feature with even the most remote use-case. It sounds (and probably is) insane. But if a feature breaks backwards compatibility, or can't be implemented in a way that non-negligibly affects compiler/IDE performance for codebases that ignore it, what's the issue? Specifically, what significant new issues would it cause that C++’s existing bloat hasn’t? C++20 isn't fully implemented in any one compiler (https://en.cppreference.com/w/cpp/compiler_support.html#C.2B.2B20_features https://en.cppreference.com/w/cpp/compiler_support.html#C.2B...).
- cemdervis 6mo agoGCC and MSVC are pretty close. fyi, the tables on cppreference are rather outdated at this point. I made a more up-to-date, community-maintained site: https://cppstat.dev/?conformance=cpp20 https://cppstat.dev/?conformance=cpp20
- KeplerBoy 6mo agowow, that's weird. One would think that updating the reference table is something a team or individual - who just spent a lot of time and effort on implementing a feature - would also do.
- tialaramex 6mo agoFor a while now cppreference.com has been in "temporary read-only mode" in which it isn't updated. Eventually I expect a "temporary" replacement will dominate and eventually it won't be "temporary" after all. Remember when some of Britain's North American colonies announced they were declaring independence? Yeah me either, but at the time I expect some people figured hey, we send a bunch of troops, burn down some stuff, by Xmas we'll have our colonies back.
- uecker 6mo agoWhy does this need to access to all my repository just for generating a PR?
- mort96 6mo agoContracts are already informally a thing: most functions have preconditions, and if you break those preconditions, the function doesn't make any guarantees of what it does. We already have some primitive ways to define preconditions, notably the assert macro and the 'restrict' qualifier. I don't mind a more structured way to define preconditions which can automatically serve as both documentation and debug invariant checks. Though you could argue that a simpler approach would be to "standardize" a convention to use assert() more liberally in the beginning of functions as precondition checks; that a sequence of 'assert's before non-'assert' code should semantically be treated as the functions preconditions by documentation generators etc. I haven't looked too deep into the design of the actual final contracts feature, maybe it's bad for reasons which have nothing to do with the fundamental idea.
- locknitpicker 6mo ago> I am somewhat dismayed that contracts were accepted. It feels like piling on ever more complexity to a language which has already surpassed its complexity budget, and given that the feature comes with its own set of footguns I'm not sure that it is justified. I don't think this opinion is well informed. Contracts are a killer feature that allows implementing static code analysis that covers error handling and verifiable correct state. This comes for free in components you consume in your code. https://herbsutter.com/2018/07/02/trip-report-summer-iso-c-standards-meeting-rapperswil/ https://herbsutter.com/2018/07/02/trip-report-summer-iso-c-s... Asserting that no one wants their code to correctly handle errors is a bold claim.
- 20k 6mo agoContracts aren't for handling errors. That blog post is extremely out of date, and doesn't reflect the current state of contracts Modern C++ contracts are being sold as being purely for debugging. You can't rely on contracts like an assert to catch problems, which is an intentional part of the design of contracts
- troupo 6mo ago> So go back about one year, and we could vote about it before it got into the standard, and some of us voted no. Now we have a much harder problem. This is part of the standard proposal. Offtopic, but this is a problem in the web world, too. Once something is on a standards track, there are almost mechanisms to vote "no, this is bad, we don't need this". The only way is to "champion" a proposal and add fixes to it until people are somewhat reasonably happy and a consensus is reached. (see https://x.com/Rich_Harris/status/1841605646128460111 https://x.com/Rich_Harris/status/1841605646128460111)
- randusername 6mo ago> It feels like piling on ever more complexity to a language which has already surpassed its complexity budget, and given that the feature comes with its own set of footguns I'm not sure that it is justified. This is a common sentiment about C++, but I find it very interesting that everyone seems to have a different feature in mind when they say it.
- estimator7292 6mo agoI think that's a clear and unambiguous point in favor of the argument. There are so many hellishly complex things in C++ that the community can't settle on even a small subset to be the worst contender. Half Life 3 rules apply. Every time someone complains about complexity in C++, the committee adds a new overly complex feature. It remains a problem because complexity keeps getting shoveled on top of the already complex language.
- DrBazza 6mo agoC++ isn't the first language to do things, but was/is often the first mainstream language to do things. And then people complain about C++ for doing it wrong, or its complexity, and show language 'X' that does it better/right, but only because they saw C++ do it first, and 'not quite right'. I expect contracts to be similar - other languages will watch, learn, and do version two, and then complain about c++, etc. It took 'quite a while' to get rid of auto_ptr, for example. If it wasn't for the fact this is a language feature, it would be better off in boost where it can be tested in the wild.
- btown 6mo agoIs there any good documentation about contracts? https://en.cppreference.com/w/cpp/language/contracts.html https://en.cppreference.com/w/cpp/language/contracts.html is incredibly confusing - its first displayed example seems to be an edge case where the assertion itself causes a mutation? https://en.cppreference.com/w/cpp/language/function.html#Function_contract_specifiers https://en.cppreference.com/w/cpp/language/function.html#Fun... is vaguely better, but still quite dense. IMO the syntax makes things hard for a newcomer to the syntax to understand, which I see as core to any programming language's goals of community. double square_root(double num) asserts_pre(num >= 0) would have been far more self-evident than just double square_root(double num) pre(num >= 0) But I suppose brevity won out.
- steveklabnik 6mo agoI believe that https://isocpp.org/files/papers/P2900R14.pdf https://isocpp.org/files/papers/P2900R14.pdf is the paper, which doesn't mean it's good documentation, as it's meant for modifying the standard. However, in its early sections, it does link to other papers which have more information, and the "proposed wording" section should be where the standardize lives, with the rest of it being context.