Comment by Night_Thastus

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

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

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

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

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

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

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

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

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

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?

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

  • 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*?).

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

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

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

      40 replies →

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.

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.

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

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

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