Back

Banned C++ features in Chromium

242 points7 dayschromium.googlesource.com
Night_Thastus7 days ago

Nothing particularly notable here. A lot of it seems to be 'We have something in-house designed for our use cases, use that instead of the standard lib equivalent'.

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.

ryandrake7 days ago

> We have something in-house designed for our use cases, use that instead of the standard lib equivalent

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.

tialaramex7 days ago

For the containers in particular this makes a lot of sense because the C++ stdlib containers are just not very good. Some of this is because C++ inherited types conceived as pedagogic tools. If you're teaching generic programming you might want both (single and double) extrusive linked list types for your explanation. But for a C++ programmer asking "Which of these do I want?" the answer is almost always neither.

The specification over-specifies std::unordered_map so that no good modern hash table type could implement this specification, but then under-specifies std::deque so that the MSVC std::deque is basically useless in practice. It requires (really, in the standard) that std::vector<bool> is a bitset, even though that makes no sense. It sometimes feels as though nobody on WG21 has any idea what they're doing, which is wild.

direwolf206 days ago

Linked lists used to be more efficient than dynamic arrays — 40 years ago, before processors had caches.

+1
dahart6 days ago
boulos6 days ago

I haven't benchmarked them myself yet, but the C++23 flat map containers are supposed to finally have fixed this. Chrome lists them as TBD: https://chromium.googlesource.com/chromium/src/+/main/styleg... .

tialaramex6 days ago

When you say "fixed this" which "this" do you think they fixed? Are you imagining this is a hash table? It's not

It's an adaptor which will use two other containers (typically std::vector) to manage the sorted keys and their associated values. The keys are sorted and their values are stored in the corresponding position in their own separate std::vector. If you already have sorted data or close enough then this type can be created almost for free yet it has similar affordances to std::map - if you don't it's likely you will find the performance unacceptable.

menaerus7 days ago

[flagged]

EliRivers7 days ago

Don't use standard library containers because we have our own containers that date back to before the STL was even stable.

Flashback to last job. Wrote their own containers. Opaque.

You ask for an item from it, you get back a void pointer. It's a pointer to the item. You ask for the previous, or the next, and you give back that void pointer (because it then goes through the data to find that one again, to know from where you want the next or previous) and get a different void pointer. No random access. You had to start with the special function which would give you the first item and go from there.

They screwed up the end, or the beginning, depending on what you were doing, so you wouldn't get back a null pointer if there was no next or previous. You had to separately check for that.

It was called an iterator, but it wasn't an iterator; an iterator is something for iterating over containers, but it didn't have actual iterators either.

When I opened it up, inside there was an actual container. Templated, so you could choose the real inside container. The default was a QList (as in Qt 4.7.4). The million line codebase contained no other uses; it was always just the default. They took a QList, and wrapped it inside a machine that only dealt in void pointers and stripped away almost all functionality, safety and ability to use std::algorithm

I suspect but cannot prove that the person who did this was a heavy C programmer in the 1980s. I do not know but suspect that this person first encountered variable data type containers that did this sort of thing (a search for "generic linked list in C" gives some ideas, for example) and when they had to move on to C++, learned just enough C++ to recreate what they were used to. And then made it the fundamental container class in millions of lines of code.

cracki7 days ago

time to refactor the code base so this tumor can be deleted?

+1
EliRivers6 days ago
LexiMax7 days ago

> 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.

The STL makes you pay for ABI stability no matter if you want it or not. For some use cases this doesn't matter, and there are some "proven" parts of the STL that need a lot of justification for substitution, yada yada std::vector and std::string.

But it's not uncommon to see unordered_map substituted with, say, sparsehash or robin_map, and in C++ libraries creating interfaces that allow for API-compatible alternatives to use of the STL is considered polite, if not necessarily ubiquitous.

pkasting6 days ago

The majority of things Chromium bans would still get banned in green-field use.

Some notable exceptions: we'd have allowed std::shared_ptr<T> and <chrono>. We might also have allowed <thread> and friends.

TeMPOraL7 days ago

> 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.

That also depends on how standalone the project is. Self-contained projects may be better off with depending on standard library and popular third-party libraries, but if a project integrates with other internal components, it's better to stick to internal libraries, as they likely have workarounds and special functionality specific to the company and its development workflow.

mihaaly7 days ago

I'd argue that the optimum was in long run to migrate to the standard version, that everyone (e.g. new employees) know. Replacing the usually particular (or even weird) way implemented own flavour.

I know, I know, long run does not exists in today's investor dominated scenarios. Code modernization is a fairytale. So far I seen no exception in my limited set of experiences (but with various codebases going back to the early 90's with patchy upgrades here and there, looking like and old coat fixed many many times with diverse size of patches of various materials and colour).

pkasting6 days ago

When I led C++ style/modernization for Chromium, I made this argument frequently: we should prefer the stdlib version of something unless we have reason not to, because incoming engineers will know it, you can find advice on the internet about it, clang-tidy passes will be written for it, and it will receive optimizations and maintenance your team doesn't have to pay for.

There are cases, however, when the migration costs are significant enough that even those benefits aren't really enough. Migrating our date/time stuff to <chrono> seemed like one of those.

mtklein7 days ago

[flagged]

acdha7 days ago

Look, I even share your language preference but this is still unnecessary.

+7
galangalalgol7 days ago
vitaut7 days ago

Somewhat notable is that `char8_t` is banned with very reasonable motivation that applies to most codebases:

> 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*.

ChrisSD7 days ago

`char8_t` is probably one of the more baffling blunders of the standards committee.

jjmarr7 days ago

there is no guarantee `char` is 8 bits, nor that it represents text, or even a particular encoding.

If your codebase has those guarantees, go ahead and use it.

+2
hackyhacky7 days ago
+2
20k7 days ago
+2
Maxatar7 days ago
+2
jhasse7 days ago
+2
dataflow7 days ago
+1
Asmod4n7 days ago
kps6 days ago

Related: in C at least (C++ standards are tl;dr), type names like `int32_t` are not required to exist. Most uses, in portable code, should be `int_least32_t`, which is required.

tarlinian6 days ago

Isn't the real reason to use char8_t over char that it that char8_t* are subject to the same strict aliasing rules as all other non-char primitive types? (i.e., the compiler doesn't have to worry that a char8_t* could point to any random piece of memory like it would for char*?).

pkasting6 days ago

At least in Chromium that wouldn't help us, because we disable strict aliasing (and have to, as there are at least a few core places where we violate it and porting to an alternative looks challenging; some of our core string-handling APIs that presume that wchar_t* and char16_t* are actually interconvertible on Windows, for example, would have to begin memcpying, which rules out certain API shapes and adds a perf cost to the rest).

vitaut5 days ago

The main effect of this is that some of the conversions between char and char8_t are inefficient.

cpeterso6 days ago

> using u8 prefixes would obligate us to insert casts everywhere.

Unfortunately, casting a char8_t* to char* (and then accessing the data through the char* pointer) is undefined behavior.

pkasting6 days ago

Yes, reading the actual data would still be UB. Hopefully will be fixed in C++29: https://github.com/cplusplus/papers/issues/592

pkasting6 days ago

It's weird to me, as the former lead maintainer of this page for ten years or so, that this got submitted to both r/c++ and HN on the same day. Like... what's so exciting about it? Was there something on the page that caught someone's eye?

torginus7 days ago

In a lot of places, they point out the std implementation is strictly inferior to theirs in some way, so its not always organizational inertia, it's that the C++ standard types could have been designed strictly better with no tradeoff.

locknitpicker6 days ago

> Nothing particularly notable here. A lot of it seems to be 'We have something in-house designed for our use cases, use that instead of the standard lib equivalent'.

The bulk of the restrictions are justified as "Banned in the Google Style Guide."

In turn the Google Style Guide bans most of the features because they can't/won't refactor most of their legacy code to catch up with post C++0x.

So even then these guidelines are just a reflection of making sure things stay safe for upstream and downstream consumers of Google's largely unmaintained codebase.

pkasting6 days ago

I don't think that's an accurate representation. There are a few features like that, but the majority of things banned in the Google style guide are banned for safety, clarity, or performance concerns. Usually in such cases Google and/or Chromium have in-house replacements that choose different tradeoffs.

That's different from an inability to refactor.

zeroq7 days ago

Not an Googler, but my, probably way too much romanticized, understanding of Google was that they never ask you about specific tech because for everything there's an in-house version.

The problem is that too many people drank too much koolaid and trying to parrot everything to a letter without understanding the bigger picture.

The best example would be Kubernetes. Employed by many orgs that have 20 devs and 50 services.

dmoy7 days ago

> for everything there's an in-house version.

Reasonable summary. There's some massive NIH syndrome going on.

Another piece is that a lot of stuff that makes sense in the open source world does not make sense in the context of the giant google3 monorepo with however many billions of lines of code all in one pile.

bengoodger7 days ago

Seeing the comments here talking about ancient codebases got me wistful for when Chromium was new and everything seemed possible.

That triggered a flash of feeling extremely old realizing we broke ground on this codebase 20 years ago this year!

Panzerschrek7 days ago

<regex> [banned]

A good decision. I tried to use it once and realized that it can't even work with UTF-8 properly. It's a mystery for me how such flawed design was standardized at all.

buckle80176 days ago

All modern regex libraries have a Unicode mode.

Also regex predates utf8.

Sharlin6 days ago

But <regex> definitely does not predate utf-8.

dnmc7 days ago

There are yet more interesting docs in the parent directory :)

https://chromium.googlesource.com/chromium/src/+/main/styleg...

ddtaylor7 days ago

Exceptions are banned, but an exception is made for Windows.

pjmlp7 days ago

People that keep bringing this up always miss the rationable that Google code was written initially in a C style that isn't exception safe.

Key takeaway => "Things would probably be different if we had to do it all over again from scratch."

"On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code, the introduction of exceptions has implications on all dependent code. If exceptions can be propagated beyond a new project, it also becomes problematic to integrate the new project into existing exception-free code. Because most existing C++ code at Google is not prepared to deal with exceptions, it is comparatively difficult to adopt new code that generates exceptions.

Given that Google's existing code is not exception-tolerant, the costs of using exceptions are somewhat greater than the costs in a new project. The conversion process would be slow and error-prone. We don't believe that the available alternatives to exceptions, such as error codes and assertions, introduce a significant burden.

Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. Because we'd like to use our open-source projects at Google and it's difficult to do so if those projects use exceptions, we need to advise against exceptions in Google open-source projects as well. Things would probably be different if we had to do it all over again from scratch."

8n4vidtmkvmk7 days ago

I'm quite happy to NOT have exceptions. I think they're a mistake as a language feature. What we need is first -class support for returning errors and propagating them, like what zig does. The next best thing are those RETURN macros that Google uses.

direwolf206 days ago

Isn't that equivalent to exceptions but more verbose and slower?

+1
invl6 days ago
hdjrudni6 days ago

Deliberately more verbose. Not sure how it'd be slower. And only a tiny bit more verbose if the language has nice keywords/syntax for you to use. The point is you want to be explicit when you're choosing to ignore an error.

pjmlp7 days ago

Having to support legacy code is a bummer. /s

Zig remains to be seen how market relevant it turns out to be.

hdjrudni6 days ago

Ya, we don't know yet. Still sitting on zig but I like what I see so far.

pkasting6 days ago

Both parts of your sentence refer to the Google style guide. This doc isn't the Google style guide. It's the Chromium modern c++ features doc. We don't talk about exceptions or platform-specific stuff (save a note on [[no_unique_address]]) in this doc.

refulgentis7 days ago

grep'd "exception" and "Windows", tl;dr only Windows reference is for `[[no_unique_address]]`. Therefore I am probably missing a joke :)

jesse__7 days ago

Might be referring to SEH ..? Just a wild guess

refulgentis7 days ago

Ah, found it: in the style guide linked from this article. https://google.github.io/styleguide/cppguide.html#Exceptions

bfrog7 days ago

This list is longer than the features in all of C I feel like at first glance. Wow that is overwhelming.

rappatic6 days ago

Yeah lord C++ is a gigantic language

Tempest19817 days ago

Where does it list the preferred alternatives to banned features?

For example:

> The <filesystem> header, which does not have sufficient support for testing, and suffers from inherent security vulnerabilities.

comex7 days ago

For most of the banned library features, the preferred alternative is listed right there in the notes. <filesystem> is one of the exceptions.

pkasting6 days ago

Yeah, maintainers would certainly +1 a CL that added a note about the parts of //base to use instead. Trivial oversight.

TheRealPomax7 days ago

Gonna venture a guess and say probably https://www.chromium.org/developers, as that's where all the information for folks who actually need to know that kind of thing lives.

jeffbee7 days ago

base/files

kazinator7 days ago

Good call on those u8"..." literals.

Source code should all be UTF-8 natively, letting you directly write UTF-8 text between quotes.

Exactly their rationale.

These literals are a solution in search of a problem ... which is real but has a much better solution.

dfajgljsldkjag7 days ago

The banned list proves that context matters more than having the newest tools. These features work well for small apps but they cause problems in a project this size.

trinix9127 days ago

IIRC a big part of Google’s coding guidelines is also about making it easy for people not heavily invested in a specific language to contribute safely. So not necessarily a project size but rather an organizational concern.

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).

jonstewart7 days ago

Go is an extremely cynical language in this regard.

loeg7 days ago

Some of it is historical reasons or portability more than anything else. Chrome is an old C++ project and evolved many of its own versions of functionality before standardization; and there's benefit to staying on its own implementations rather than switching.

diabllicseagull7 days ago

Agreed. I also prefer conformity over sporadic use of new features going against an already set of standards in a codebase. it's overall less cognitive load on whoever is reading it imho.

WalterBright7 days ago

Modules are banned - they should have just copied D modules.

random_mutex6 days ago

Because of compiler support

WalterBright6 days ago

Which suggests (and I don't know this for a fact) that C++ modules are difficult to implement. D's are easy.

I would have made C++ modules be a slightly modified namespace.

pkasting6 days ago

C++ module implementation is a story with a lot of drama, if you ever want to read up on it.

The short summary, though, is that no toolchain yet has a bulletproof implementation, though everybody at least has enough to let people kick the tires a bit.

GnarfGnarf6 days ago

I thought User-Defined Literals were a great idea until I saw all the pitfalls listed in the Google style document. Dangerous indeed.

pkasting6 days ago

FWIW, I still think the Google Style Guide banning UDLs entirely is too harsh. I think they should be used sparingly, but there are cases where they make sense.

In Chromium's UI code, we have a lot of APIs that deal with coordinates, which may be in either px or dp. And we have a lot of code that needs to hardcode various constants, e.g. layout values for different dialogs. IMO, it's sane to have UDL support here, e.g. `20_px` (at least if we had separate types to represent these two things, which we don't... don't get me started).

GnarfGnarf6 days ago

Agree. I love UDLs, use them in my code for improved legibility. I hadn’t realized how badly you can screw up if you don’t define all the operators correctly.

amelius7 days ago

Is there a way to make this formal, like in the code, making the compiler complain when you try to use these features?

6r177 days ago

I'm not a c++ user but i'm pretty sure you should be able to pull-off a macro to do that ; in c you could alias the lib for something that breaks + alert ; I don't know how I would integrate such additional compiler checks in rust for other kinds of rules however - it's interesting to think about

pkasting6 days ago

We have a linter that checks for most of them as a pre-upload hook.

TingPing7 days ago

It’s a bit different, but WebKit uses Clangs static analysis.

loeg7 days ago

It is relatively easy to check these things with static analyzers, if nothing else.

mkoubaa7 days ago

Kythe can be used for that

weinzierl7 days ago

I'd curious about the banned Rust features. Surely, Rust has at lot fewer foot guns, but it isn't that there aren't any.

tialaramex6 days ago

Rust has been better than C++ about marking where there's a foot gun and where practical just nerfing it. core::mem::uninitialized() is an example. In 2016 if you'd said "Initializing my Doodad is too expensive, what do I do?" you might be pointed at the (unsafe) core::mem::uninitialized() which "initializes" any variable, such as your Doodad but er, doesn't actually initialize it.

But that's a foot gun, there are niche cases where this crazy stunt actually is correct (ZSTs are one), but in general the compiler was in effect licensed to cause absolute mayhem because this isn't a Doodad at all, which isn't what you wanted. So, they did three things:

1. Made a new type wrapper for this purpose, MaybeUninit<Doodad> might not be a Doodad yet, so we can initialize it later and until then the compiler won't set everything on fire but it's the same shape as the Doodad.

2. Marked core::mem::uninitialized deprecated. If you use it now the compiler warns you that you shouldn't do that.

3. De-fanged it by, despite its name, scrawling the bit pattern 0x01 over all the memory. The compiler can see this has some particular value and for common types it's even valid, a bool will be true, a NonZeroU32 will be 1, and so on. This is slow and probably not what you intended, but we did warn you that it was a bad idea to call this function still so...

jtrueb7 days ago

Heard of `#![forbid(unsafe_code)]` ?

bulbar7 days ago

It's that effectively enforcement of features that are banned?

tialaramex6 days ago

Rust's compiler has six what it calls "lint levels" two of which can't be overridden by compiler flags, these handle all of its diagnostics and are also commonly used by linters like clippy.

Allow and Expect are levels where it's OK that a diagnostic happened, but with Expect if the diagnostic expected was not found then we get another diagnostic telling us that our expectation wasn't fulfilled.

Warn and Force-Warn are levels where we get a warning but compilation results in an executable anyway. Force-warn is a level where you can't tell the compiler not to emit this warning.

Deny and Forbid are levels where the diagnostic is reported and compilation fails, so we do not get an executable. Forbid, like Force-warn cannot be overriden with compiler flags.

jenadine7 days ago

#![deny(clippy::unwrap_used)]

weinzierl7 days ago

I doubt unsafe would be blatantly banned. I was more thinking of things like glob imports.

lateforwork7 days ago

You almost never see a list of banned Java features (or even banned C# features). On the other hand any serious C++ development team is going to have a list of banned features. Java eliminated the features that you would want to ban.

nilamo7 days ago

This seems factually incorrect and ignorant of history. Java has tons of things which shouldn't be used. Serialization (use Jackson now, not the built-in stuff), date/time (there's an entirely different namespace so you don't accidentally use garbage classes), etc.

C# similarly has old warts that are discouraged now. .NET Framework is a great example (completely different from modern c#, which used to be called "dotnet core"). WPF and MAUI are also examples. Or when "dynamic" was used as a type escape hatch before the type system advanced to not need it. ASP being incompatible with ASP.NET, the list goes on.

They're just languages, there's no reason to pretend they're perfect.

twisteriffic7 days ago

> C# similarly has old warts that are discouraged now. .NET Framework is a great example (completely different from modern c#, which used to be called "dotnet core"). WPF and MAUI are also examples. Or when "dynamic" was used as a type escape hatch before the type system advanced to not need it. ASP being incompatible with ASP.NET, the list goes on.

Almost all of this is incorrect or comparing apples to oranges.

.net framework and .net core are runtime and standard library impl, not languages. C# is a language that can target either runtime or both. Framework is still supported today, and you can still use most modern C# language features in a project targeting it. WPF and Maui are both still supported and widely used. ASP predates .net - c# was never a supported language in it. ASP.net core has largely replaced ASP.net, but it's again a library and framework, not a language feature.

Dynamic in c# and the dlr are definitely not widely used because it's both difficult to use safely and doesn't fit well with the dominant paradigm of the language. If you're looking for STD lib warts binaryserializer would have been an excellent example.

tubs7 days ago

Dynamic is still nice when you’re dealing with unknown data imo. More hygienic to read than dictionary access through string keys for example.

I use it when deserializing unknown message types.

Kwpolska7 days ago

C# can be used in both .NET Framework and modern .NET (ex-core). In fact, it is possible for a C# project to target both .NET Framework and .NET with the exact same code, or to target to .NET Standard, where the same .DLL file can be loaded by both. Since the old Framework is in maintenance mode, some modern language features will not work there, but you can still be productive with the old framework.

Dynamic is largely unnecessary, and it was unnecessary even when it was introduced.

ASP and ASP.NET are completely unrelated. ASP was designed to allow dynamic webpages to be written in VBScript (like CGI). This is not something you want to do in modern languages.

lateforwork7 days ago

Those are libraries not language features.

plorkyeran7 days ago

So is nearly all of this list.

+1
lateforwork7 days ago
bathtub3657 days ago

dynamic is a language feature

oldmanhorton7 days ago

In C#, you would normally implement rules like this with a custom Roslyn Analyzer or with https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyze.... It’s fair to say C# projects tend to have smaller denylists than mature C++ projects, but banned APIs definitely exist in mature C# projects.

jameslars7 days ago

I think Java has plenty of features that end up implicitly banned at least. e.g. you will really never see a `java.util.Vector` in any modern code base. No one `implements Serializable` anymore in practice. `Objects.equals()` and `Objects.hashCode()` get you through 99% of equals/hash code implementations. The list goes on.

I guess the difference is it's rarely "dangerous" or "hard to reason about" using the old features unlike what I see in the C++ list. Java replaces things with better things and momentum shifts behind them kind of naturally because the better things are objectively better.

AdieuToLogic7 days ago

> You almost never see a list of banned Java features ...

The instanceof[0] operator is typically banned from use in application code and often frowned upon in library implementations.

0 - https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.htm...

twic7 days ago

I've never heard of that being banned. It hasn't been banned anywhere i've written Java.

gpderetta7 days ago

Similarly I never been in a company that outright banned c++ language of library features[1]. Turns out that different companies are different.

[1] I guess you would get some push back at review time if you used auto_ptr.

AdieuToLogic5 days ago

> I've never heard of that being banned. It hasn't been banned anywhere i've written Java.

Once code such as the below is rejected in a code review, the next version often submitted is an "if-else-if" ladder using `instanceof` (which is effectively the same thing).

  TheReturnType r = null;

  try {
    DomainType1 instance = (DomainType1)obj;

    r = ...
    }
    catch (ClassCastException ex) {}

  if (r == null)
    try {
      DomainType2 instance = (DomainType2)obj;

      r = ...
      }
      catch (ClassCastException ex) {}

  if (r == null)
    try {
      DomainType3 instance = (DomainType3)obj;

      r = ...
      }
      catch (ClassCastException ex) {}

  ...
And yes, I have seen the above scenario played out in a professional setting.
MrBuddyCasino7 days ago

Never seen this being banned. Whats the reason?

blandflakes6 days ago

If you have to ask an object what its type is, you're probably about to cast it, and these are operations that the language doesn't enforce that you do together (and so the habit of casting can lead to the habit of casting without the check...). There are times when it's appropriate but generally if you have to ask what type an object is, your code is already starting to smell (because typically dispatching on type is handled by polymorphism, not be the programmer manually implementing it).

AdieuToLogic5 days ago

>> The instanceof[0] operator is typically banned from use in application code and often frowned upon in library implementations.

> Never seen this being banned. Whats the reason?

Its usage encodes a priori assumptions of what a super-type could be, often expressed in an "if-else-if tree", thus making the logic doing so needlessly brittle and difficult to maintain.

Library logic sometimes needs to use this construct (I'd argue those abstractions need to be rethought however), but an application which does exhibits a failure in domain modelling IMHO.

MrBuddyCasino5 days ago

It can be a code smell, but there are legitimate uses. This is not something that I would ever "ban".

Over-eager code analyser tools are themselves a "smell", in that you either justifiably or unjustifiably don't trust your developers, trying to make up for their real or perceived deficits with a rather dumb tool. That never goes well in my experience.

MBCook7 days ago

As a Java programmer I can only think of one thing:

Reflection - unless you really need to do something fancy almost certainly a very bad idea in normal application code.

Other than that it’s either just limiting yourself to a specific JVM version or telling people not to use old syntax/patterns that were replaced with better options long ago.

pjmlp7 days ago

I have, many companies have style guides enforced via Sonar and similar tools, what you don't see is everyone putting them on the Internet.

Sharlin6 days ago

Java has so few features that there's not much to ban. Nevertheless Java definitely has language features (in addition to deprecated library APIs, which are many) that aren't recommended today. Off the top of my mind:

* `synchronized` blocks

* raw types

* anonymous inner classes

* checked exceptions

as well as specific uses of otherwise fine language features:

* "AbstractX" style abstract classes when static and default interface methods suffice

* old-style POJO classes when records are a better choice

lateforwork6 days ago

> Java has so few features that there's not much to ban

Exactly. Simplicity was an explicit design goal of Java.

Most items in your list are fine actually, including raw types and inner classes.

Regarding checked exceptions, it is unfortunate that people don't fully understand it, see here: https://mckoder.medium.com/the-achilles-heel-of-c-why-its-ex...

madeofpalk7 days ago

I would imagine most codebases, even in modern languages, tend to have a list of banned features. Typically you use a linter to catch these.

spixy7 days ago

Unless you develop games in Unity, and have banned C# features like classes or LINQ (because they allocate on heap and Unity garbage collector is bad and make your game to micro freeze / stutter). Sure there are cases where classes are fine (singletons, pooling), but still...

jesse__7 days ago

It's remarkable to me how many codebases ban exceptions and yet, somehow, people still insist they're good.

BeetleB7 days ago

> Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. ... Things would probably be different if we had to do it all over again from scratch.

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).

jesse__7 days ago

My issue with exceptions is also practical. If they didn't introduce significant stability issues, I'd have no problem. As it stands, it's impossible to write robust software that makes use of C++ exceptions.

> the compiler will require you to deal with it somehow in g

I agree, this is the sensible solution.

yunnpp7 days ago

What stability issues?

+2
rauli_7 days ago
jandrewrogers7 days ago

In low-level systems software, which is a primary use case for C++, exceptions can introduce nasty edge cases that are difficult to detect and reason about. The benefits are too small to justify the costs to reliability, robustness, and maintainability.

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.

drnick17 days ago

> In low-level systems software, which is a primary use case for C++

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.

+1
saghm7 days ago
BeetleB7 days ago

> In low-level systems software, which is a primary use case for C++

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.

beached_whale7 days ago

The model of communicating errors with exceptions is really nice. The implementation in C++ ABI's is not done as well as it could be and that results in large sad path perf loss.

+1
jandrewrogers7 days ago
kllrnohj7 days ago

If you forget to handle a C++ exception you get a clean crash. If you forget to handle a C error return you get undefined behavior and probably an exploit.

Exceptions are more robust, not less.

+1
nomel7 days ago
LexiMax6 days ago

> If you forget to handle a C++ exception you get a clean crash

So clean that there's no stack trace information to go with it, making the exception postmortem damn near useless.

+2
Expurple7 days ago
beached_whale7 days ago

C++ exceptions are fast for happy path and ABI locked for sad path. They could be much faster than they are currently. Khalil Estell did a few talks/bunch of work on the topic and saw great improvements. https://youtu.be/LorcxyJ9zr4

beached_whale7 days ago

Oops, I meant they are ABI locked so sad path cannot be fixed.

senfiaj7 days ago

> "In low-level systems software, which is a primary use case for C++, exceptions can introduce nasty edge cases that are difficult to detect and reason about. The benefits are too small to justify the costs to reliability, robustness, and maintainability."

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.

jandrewrogers7 days ago

FWIW, I think it is possible to make exception-like error handling work. A lot of systems code has infrastructure that looks like an exception handling framework if you squint.

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.

matheusmoreira7 days ago

Exceptions are actually a form of code compression. Past some break even point they are a net benefit, even in embedded codebases. They're "bad" because the C++ implementation is garbage but it turns out it's possible to hack it into a much better shape:

https://youtu.be/LorcxyJ9zr4

secondcoming7 days ago

There is no such thing as the 'C++ implementation' of exceptions. Each vendor can do it differently.

jayd167 days ago

Is this correct? I don't know F# but I thought it had unchecked exceptions. How does it handle using C# libs that throw unchecked exceptions?

BeetleB7 days ago

My memory of F# is very rusty, but IIRC, there are two types of error handling mechanisms. One of them is to be compatible with C#, and the other is fully checked.

+1
lateforwork7 days ago
heyitsdaad7 days ago

The “pros” list is exceptionally weak. This was clearly written by someone who doesn’t like exceptions. Can’t blame them.

azov7 days ago

Most codebases that ban exceptions do it because they parrot Google.

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.

alextingle7 days ago

I agree. I've worked on large C++ code bases that use exceptions, and they've never caused us any real problems.

ryandrake7 days ago

I think reasonable people can disagree about whether C++ exceptions are "good" or not.

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.

canucker20167 days ago

For exception-less C++, you'd declare an operator new() that doesn't throw exceptions and just returns NULL on allocation failure along with a simple constructor and a followup explicitly-called init() method that does the real work which might fail and returns an error value on failure.

tester7567 days ago

They're good for exceptional situations where foundamental, core assumptions are broken for some reason.

In such scenario there's no error recovery, software is expected to shutdown and raise loud error.

jesse__7 days ago

If you're planning on shutting down, what's the fundamental difference between throwing an exception, vs simply complaining loudly and calling exit() ..?

trinix9127 days ago

Sometimes it’s useful to handle the exception somewhere near its origin so you can close related resources, lockfiles, etc. without needing a VB6 style “On Error GoTo X” global error handler that has to account for all different contexts under which the exceptional situation might have occurred.

+1
PhilipRoman7 days ago
matheusmoreira7 days ago

> a VB6 style “On Error GoTo X” global error handler that has to account for all different contexts under which the exceptional situation might have occurred

... That seems like a pretty accurate description of how exception handling mechanisms are implemented under the hood. :)

einpoklum7 days ago

The code that's throwing an exception typically does not know that the exception catcher will shut anything down.

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.

spacechild17 days ago

> They're good for exceptional situations where foundamental, core assumptions are broken for some reason.

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 :)

ljm7 days ago

Yet, if you can only explain an exception using the word ‘exception’ you’re not making any head way.

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.

dijit7 days ago

I use asserts for this purpose.

wvenable7 days ago

Looking at this ban list, they've removed everything from C++ that makes it fun. Come on people, who doesn't love a little std::function?!?

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

pkasting6 days ago

We have base::Callback for when you'd reach for std::function, which provides superior safety.

nixosbestos7 days ago

Rust is too complicated!!11 Ooops wrong thread.

grougnax7 days ago

C++ itself should be forever banned

j16sdiz7 days ago

Ok. You can stop using anything written in C++.

Expurple7 days ago

How would you implement a C++ ban in Chromium?

einpoklum7 days ago

Since Chromium stopped allowing manifest-v2 extensions, i.e. significantly crippled what extensions can do and made it impossible to use some key extensions like uBlock Origin, I've decided to avoid it.

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.)

don-bright6 days ago

I spent a while on an open source project debugging some bizarre crashes. Cant remember exact detail but something like Someone was throwing an exception inside a destructor which had been triggered inside another exception. It was layers deep inside a massively templated 3rd party dependency library. so I like wound up parsing the string in the exception message and doing weird logic to make the program keep going since the exception wasnt actually a dire situation as far as the main program was concerned. So Exceptions can be fine in theory but I understand the idea that a ban can simplify a lot of things.

jsheard7 days ago

If nothing else Abseil gives you state-of-the-art hashmaps that run circles around the STL ones, which are slow pretty much by definition. The spec precludes the modern ways of implementing them.

einpoklum7 days ago

Indeed, the standard library maps are quite slow, and I often point that out to people:

https://stackoverflow.com/a/42588384/1593077

But you can and should use non-std state-of-the-art hashmaps without living in the world of abseil.

pkasting6 days ago

Sure; you can roll your own, or you can use one of the many other libraries that provide alternatives. There are obvious downsides to the former, and the latter is basically equivalent to using the Abseil ones in terms of practical tradeoffs.

Chromium uses hundreds of other open source libraries. Is there something about Abseil specifically that sticks in your craw?

crazygringo6 days ago

You know uBlock Origin Lite works great with v3 and is significantly faster than v2. I actually prefer it.