It is deeply integrated into the C++11 memory model. The compiler has to know about the semantics of the type to make sure it doesn’t reorder operations around it.
> No C++ Standard Library / Exceptions / RTTI
It seems like you know C++ pretty well, so I think you could probably come up with some reasons if you gave it a try.
The obvious thing that comes to my mind is because you can't rely on an undesirable, unknown, or potentially nonexistent implementation of the STL for your target platform.
As for cookies: who am I to dictate what/how someone should bake?
Otherwise good luck porting that exception free code across multiple OSes and C++ compilers, not only the big three.
Here-in lies the problem. This only says “no std::exception” “no throw” but nothing is stopping you from writing your own template for error handling. An exception is by definition a “unexpected condition” and we all have to handle exceptions in some form or fashion. Whether that’s with error codes, macro checks, or the like. That’s my point. Exception free code doesn’t exist. Safety guarantees are compile time at best. If this weren’t true, things like memory manipulation wouldn’t be possible. But it is. CheatEngine exists. Funnest thing is to read a var, set a var, and then check if the set var equals the set value or if it equals the old value. You just detected a memory pin cheat.
There is a "turn code into object file using compiler" C++, that is much different from "committee vision" C++, and until recently (probably until initializer lists), -fno-exceptions -fno-rtti -ffreestanding did not emmit standard library symbols, except maybe static initialization.
Current C++ is being glued to library like crazy, look at continuations...
In some vanilla app code exceptions are fine, but they introduce nasty edge cases in the kinds of systems code architectures C++ is mostly used for these days. Additionally, they don’t solve an urgent problem in practice that would strongly incentive someone to use them, so it the price of admission is rather steep for minimal benefit.
It is trivial to “guarantee” the underlying memory and is idiomatic for a lot of software that cares about performance or reliability. That is code anyone can write if they care. There isn’t much that can go wrong with memory allocation if you are not allocating memory from the system. No one is requiring C++ developers to poorly duct tape a bunch of rubbish STL together and call it an app. That simply isn’t something you see much in the hardcore systems domains where C++ is the tool of choice.
Somehow, mission-critical software is routinely written in C++ without exceptions and it works just fine. Error states are a normal part of all code, no exceptions required since obviously many languages don’t have them. And no, the alternative is not a segfault. C++ is designed to work just fine without exceptions. The language allows you to bring your own error/exception handling models with minimal overhead, same way you can import alternative ownership/safety models.
An error and an exception are the same concept. Yes, it’s true that not using the std::exception class or any template named “exception” is exception free code. But you’re just lying to yourself. An error check or an assert or verify not <condition> is a “catch”.
I really wish that everyone that plagues C++ library fragmentation with disabled this, disabled that, just stick to C and leave C++ community alone, so that we can fully enjoy the language as designed.
I guess we need something else everyone can agree upon.
Until then, the computing foundations will kept be being written in C++, until some big name decides to rewrite LLVM, GCC and VC++ into something else.
One large open source project that is using Exception free C++ is SerenityOS for example https://github.com/SerenityOS/serenity
The best way to write proper exception free C++ is not to use the C++ Standard Library.
Only in C++ land do developers delusion themselves into thinking their way isn’t this way. That exception free means just simply not doing try/catch. jandrewrogers made a good argument below about memory safety and allocations in regards to mission-critical code but even in that scenario, underlying memory can be manipulated by MITM or other conditions that could cause corruption or segfaults in allocator pages.
I think that handling errors with ErrorOr<T,E> or similar techniques (I use something similar too) is very different from exception handling.
My main problems with exception handling are:
1. It's not zero-overhead (brings in RTTI often) 2. You can't know if a function throws something by looking at its signature 3. You don't know what types exceptions a function can throw 4. It doesn't force users to handle errors that can happen, leading tomore "happy path" style code
Something like ErrorOr or similar with [[nodiscard]] ticks all the above 4 points.
ErrorOr is a better design for things to be deterministic. The point I was trying to make is that exceptions are errors and error handling and exception handling (while implemented differently) are essentially the same thing. In C++ std::exception is “exceptions” and everything else is “pretty error”. It doesn’t matter how the house is decorated. Exceptions = Errors = Oopsies = NotIntendedState
I'm not going to talk about errorOr specifically because I don't know how it's implemented but rather your premise.
Exceptions are the modern goto, the try catch may be in the caller function. Or it could be 3 inherented classes away (this is hyperbole, I'm not sure if it would actually work) with so much indirection it would be impossible to follow the code flow other than to step in a debugger. So in fact it's worse than a goto since at least a goto had a label.
I'm not for or against exceptions just pointing out that a result or optional type is in no way at all similar to an exception.
On another point C++ exceptions are notoriously inefficient as well. There ware valid reasons to want to be exception free even from a code style perspective.
How are pubsub systems a modern goto? Genuinely curious since I don't work with them directly that often
Observer pattern is fine, because there is still a link between the execution flow; basically any time you register a callback you're using the observer pattern.
Pubsub adds a middleware, typically in the form of a message passing framework, so that both publisher and subscriber aren't necessarily aware of each others existence. The publisher throws its data into the framework hoping someone finds it useful, and the subscriber listens for those messages hoping someone is publishing them. Think of it like multithread asynchronous goto of your execution flow, except with a lot more boilerplate.
This is all in an effort to bring down compile times, avoiding including anything from the standard because you can never know if including <atomic> is bringing 10K lines of code in your header.
I will probably provide an optional USE_STANDARD_HEADERS flag someday to allow including a few standard things, including atomics, to avoid doing things wrong on compilerS that are not tested enough (as I clearly can't test every compiler).