The rest looks very reasonable, like avoiding locale-hell.
Some of it is likely options that sand rough edges off of the standard lib, which is reasonable.
Yea, you encounter this a lot at companies with very old codebases. Don't use "chrono" because we have our own date/time types that were made before chrono even existed. Don't use standard library containers because we have our own containers that date back to before the STL was even stable.
I wonder how many of these (or the Google style guide rules) would make sense for a project starting today from a blank .cpp file. Probably not many of them.
> Use char and unprefixed character literals. Non-UTF-8 encodings are rare enough in Chromium that the value of distinguishing them at the type level is low, and char8_t* is not interconvertible with char* (what ~all Chromium, STL, and platform-specific APIs use), so using u8 prefixes would obligate us to insert casts everywhere. If you want to declare at a type level that a block of data is string-like and not an arbitrary binary blob, prefer std::string[_view] over char*.
https://chromium.googlesource.com/chromium/src/+/main/styleg...
For example:
> The <filesystem> header, which does not have sufficient support for testing, and suffers from inherent security vulnerabilities.
They’d rather see it done the same way it would’ve been in any other similar language than with a language specific feature.
There are also portability concerns in mind given that projects like Chromium have to be easily portable across a vast amount of platforms (this shows with things like long long which is also on the list).
Anyway, about these C++ conventions - to each software house its own I guess. I don't think banning exceptions altogether is appropriate; and I don't see the great benefit of using abseil (but feel free to convince me it's really that good.)
They are clearly not against them per se. It simply wasn't practical for them to include it into their codebase.
And I think a lot of the cons of exceptions are handled in languages like F#, etc. If f calls g which calls h, and h throws an exception, the compiler will require you to deal with it somehow in g (either handle or explicitly propagate).
> the compiler will require you to deal with it somehow in g
I agree, this is the sensible solution.
Exceptions in high-level languages avoid many of these issues by virtue of being much further away from the metal. It is a mis-feature for a systems language. C++ was originally used for a lot of high-level application code where exceptions might make sense that you would never use C++ for today.
I don't this this is true. There is A LOT of C++ for GUI applications, video games, all kind of utilities, scientific computing and others. In fact, I find that the transition to "modern" alternatives from native GUI toolkits in C/C++ has led to a regression in UI performance in general. Desktop programs performed better 20 years ago when everything was written in Win32, Qt, GTK and others and people did not rely on bloated Web toolkits for desktop development. Even today you can really feel how much more snappy and robust "old school" programs are relative to Electron and whatnot.
I can assure you: Most C++ SW is not written for low-level.
> exceptions can introduce nasty edge cases that are difficult to detect and reason about.
That's true, except for languages that ensure you can't simply forget that something deep down the stack can throw an exception.
BTW, I'm not saying C++'s exceptions are in any way good. My point is that exceptions are bad in C++, and not necessarily bad in general.
Sometimes it is not safe to unwind the stack. The language is not relevant. Not everything that touches your address space is your code or your process.
Exception handlers must have logic and infrastructure to detect these unsafe conditions and then rewrite the control flow to avoid the unsafety. This both adds overhead to the non-exceptional happy path and makes the code flow significantly uglier.
The underlying cause still exists when you don't use exceptions but the code for reasoning about it is highly localized and usually has no overhead because you already have the necessary context to deal with it cleanly.
Exceptions are more robust, not less.
Interestingly, Microsoft C / C++ compiler does support structured exception handling (SEH). It's used even in NT kernel and drivers. I'm not saying it's the same thing as C++ exceptions, since it's designed primarily for handling hardware faults and is simplified, but still shares some core principles (guarded region, stack unwinding, etc). So a limited version of exception handling can work fine even in a thing like an OS kernel.
There are two main limitations. Currently, the compiler has no idea what can be safely unwound. You could likely annotate objects to provide this information. Second, there is currently no way to tell the compiler what to do with an object in the call stack may not be unwound safely.
A lot of error handling code in C++ systems code essentially provides this but C++ exceptions can't use any of this information so it is applied manually.
There are things you can't do easily in C++ without using exceptions, like handling errors that happen in a constructor and handling when `new` cannot alloc memory. Plus, a lot of the standard library relies on exceptions. And of course there's the stylistic argument of clearly separating error-handling from the happy-path logic.
I won't argue that it's popular to ban them, though. And often for good reasons.
Google’s reasons for banning exceptions are historical, not technical. Sadly, this decision got enshrined in Google C++ Style Guide. The guide is otherwise pretty decent and is used by a lot of projects, but this particular part is IMO a disservice to the larger C++ ecosystem.
In such scenario there's no error recovery, software is expected to shutdown and raise loud error.
No, that's what assertions or contracts are for.
Most exceptions are supposed to be handled. The alternative to exceptions in C++ are error codes and `std::expected::. They are used for errors that are expected to happen (even if they may be exceptional). You just shouldn't use exceptions for control flow. (I'm looking at you, Python :)
... That seems like a pretty accurate description of how exception handling mechanisms are implemented under the hood. :)
And - very often, you would _not_ shut down. Examples:
* Failure/error in an individual operation or action does not invalidate all others in the set of stuff to be done.
* Failure/error regarding the interaction with one user does not mean the interaction with other users also has to fail.
* Some things can be retried after failing, and may succeed later: I/O; things involving resource use, etc.
* Some actions have more than one way to perform them, with the calling code not being able to know apriori whether all of them are appropriate. So, it tries one of them, if it fails tries another etc.
I like the idea of an exception as a way to blow out of the current context in order for something else to catch it and handle in a generic manner. I don’t like the idea of an exception to hide errors or for conditional logic because you have to know what is handling it all. Much easier to handle it there and then, or use a type safe equivalent (like a maybe or either monad) or just blow that shit up as soon as you can’t recover from the unexpected.
On banning exceptions:"Things would probably be different if we had to do it all over again from scratch."
https://google.github.io/styleguide/cppguide.html#Exceptions