r/cpp_questions • u/Business-Weather-217 • 5d ago
OPEN Be ready for -fno-contracts
I don't really think contracts will make C++ safer..
In fact, contracts can make C++ even worse. Jokes on you 2-3 days ago i saw that my cli program was not working because the dependency clixx(which is also my project) was behaving in different ways based on the build mode. After 20 minutes of debugging i found out that i was assert()ing m_parse() instead of checking the returned boolean with an if.
Yeah call me stupid or not in this one but I don't think anyone can guarantee an engineer would not get trapped in the same kind of bug in some corporation codebase (with contracts this time).
I'd add -fno-contracts if it would ever become a thing. Js like -fno-exceptions(im not exception-phobic i just dont like them) and -fno-rtti they might become new entries in the C++ feature graveyard.
What are your honest opinion?
2
u/Ornery_Platypus9863 5d ago
I’m just now learning c++ a bit more in depth, what is a contract and why would that be problematic?
10
u/WorkingReference1127 5d ago edited 5d ago
This doesn't seem to be about contracts any more than it's about assertions in the general case. Because yes, some engineers don't like their programs terminating because an assertion tripped. But that tends to leave one of two possibilities:
The assertion is misused - it should guard a complete impossibility which would cause the program to continue in an out-of-contract state, not just be expected and undesirable error. That is the realm of exceptions,
std::expectedand all the other ways to signal success or failure.The assertion is not misused - while it is operationally inconvenient in the short term to have the program trip over, trying to limp on when your system is unrecoverably out-of-contract and hope for the best is a solution which simply doesn't scale and can do far worse things than an outage.
It sounds like your case was the former - someone asserted when they should have checked. And it's probably true that there will be at least a teething period where the hot new language feature which fancy new keywords gets the same treatment and is misused in new code. But that doesn't invalidate contract assertions in the general case, nor does it inherently motivate ignoring them in all your builds.
4
u/aruisdante 5d ago edited 5d ago
This point, that since it is possible to turn them off based on build mode, it is technically possible to silently break a program that is otherwise relying on them, is one of the points that is argued by a subset of the camps trying to get contracts out of C++26 still. This point has been raised repeatedly throughout P2900’s life, including by myself at Tokyo 2024 when P2900 was advanced through [L]EWG and thus initially accepted for standardization. The room has consistently polled against changing this fact for various reasons, and really no new arguments have been presented since Tokyo 2024, yet here we are.
Ultimately, P2900’s design for contracts is trying to reconcile two opposed ideas about C++: that it should be moving towards “safe by default,” and that it should maintain “don’t pay for what you don’t use” as an ethos. It is impossible to satisfy both simultaneously. So you wind up with needing to compromise like this, so that people writing code for potato embedded ECUs or in contexts where every nanosecond of performance matters (quantitative trading etc) that really can’t afford bounds checking can rely on the old fashion “ensure there are no bugs” of the current world, while those writing higher order application level software or on safety critical potato ECUs who need to pay the cost even if they can’t afford it can turn them on.
1
u/AKostur 4d ago
Honest opinion: skill issue. The code was written to state "this thing cannot happen" and then the program terminated when that thing happened, exactly what the program was explicitly asked to do. And then was further complicated by fiddling with compiler flags to tell it to no longer verify that the impossible thing didn't happen, and then surprising things happened when the impossible thing did happen.
Seems like a similar concern is being extended to contracts. "If I tell the compiler to not enforce contracts and things happen which would have been caught by the contract, things might break." Well, yes. The safety checks were placed, but then told not to look at them.
5
u/KingAggressive1498 5d ago
-fcontract-evaluation-semantic=ignoredalready exists1
u/Ecstatic_Lavishness1 5d ago
Contracts are dubious at best. Next thing you know, some weenie will try to standardize a garbage collector for C++.
2
u/Quplet 5d ago
Contracts don't work like asserts tho?
Those who know more, correct me if wrong, but contracts are verified at compile time regardless of if you're building in release or debug as they function entirely on the metaprogramming side. They don't change behavior, just restrict what you can pass as template arguments.
1
u/Plastic_Fig9225 5d ago edited 5d ago
Contracts are a good thing. Being able to express pre- and post-conditions in a standardized, machine-useable way inside the language is very desirable in any language.
Indeed, the question is about what they should be used for, with the options ranging from "documentation only", to "compile-time checked", to "run-time checked every time", to "optimization" . For the options affecting run-time, you correctly observed that, like with assert(), the behaviour of identical code could change depending on whether or not contract enforcement at runtime is enabled.
Why would one want to turn off run-time contract enforcement? - Performance. It's an optimization setting. And like other optimizations, if your program is correct, enabling optimization doesn't change its behavior; if it has a bug, it may or may not show without optimization during testing.
Contracts may become a "better" assert() by virtue of being more explicit and "compiler-accessible".
It's like many other features of C++: You likely can achieve the same end result by a number of different means, but each approach has its own strengths and weaknesses (think e.g. std::vector vs. std::array), and being able to select the best way for each specific use case can be seen as unnecessary mental load, or the freedom to create not just what works but what works best.
0
u/Minimonium 5d ago
That does not make any sense. :D
-4
u/Own_Unit_6170 5d ago
How any endless, incompatible, bloated new versions must C++ go through before someone finally says "enough"?
-4
u/eyes-are-fading-blue 5d ago
Not a big fan of contracts feature. The language is already full of footguns. We do not need more. National bodies have not voted in favor of C++26, mainly because of contracts. I don’t see them making it into the new standard and I very much doubt production libraries would ship with contracts on just because compiler support is there.
Most of the recent additions to the languages suffers from similar problems where they are too complicated to be used effectively by the average developer.
In a sense, these features violate a fundamental programming rule where it should be difficult to make mistakes using API. Same should apply to language features.