Hacker News new | ask | show | jobs
by cletus 2763 days ago
Having written C++ at Google using these (strictly enforced) style guidelines, I actually kind of likes Google's subset of C++.

It should be noted that any reasonably sized shop uses a subset of C++. It's insanity not to. It's just a question of what to allow and what not to.

Google C++ uses a style of error-handling that's akin to how Go handles errors. Many functions return a util::Status (which would be OK or an error) or, when you needed to return a value, return a util::StatusOr<T>.

Some people who write Go rail against the verbosity of this. I actually like it because it makes it pretty easy to reason about what your code is doing without the flow control you can get from exceptions.

There are definite warts in the codebase. One big one I remember was that one of the early developers (which might've been Craig Silverstein) didn't believe in unsigned types so there are a bunch of size functions that return an int and this has caused no end of problems.

I'm no C++ expert so I can't speak to some of the author's gripes (eg pragma-once vs #define/#ifndef) but a lot of the criticisms suggest that the author hasn't worked on large codebases.

Take operator overloading. This is fine, in theory, if used judiciously. The problem is engineers differ on what's reasonable and this may lead to unexpected behaviour, particularly when you start factoring in automatic type conversions. You see this in Scala, for example, where people go nuts, basically because they can and for no other reason.

There's a certain type of engineer who gets trapped in a mindset where they start considering complexity a virtue. I once got into a discussion with someone where he was shocked that I didn't know what perfect forwarding was. After looking it up I was like "why do I need to know this (unless I'm writing a templated library)?" and the answer is I don't.

Google's C++ style guide is largely about avoiding these flights of fancy making it into codebases that other people rely on, may need to debug, etc. And it achieves that goal as I found Google C++ code quite readable on the whole.

There's still a lot of code that doesn't, say, use smart pointers, so you can get dereferencing errors if you're not careful or if you don't understand who owns what. And this isn't something that C++11/14/17 smart pointers are perfect at anyway (something I'm quite bullish about for Rust, in comparison).

Another example: the complaint about no reference arguments. The point of this is so you can't tell what function arguments might be mutated if you allow non-const reference function arguments whereas with pointers it's obvious. To be clear:

    foo(c); // could be pass by value or reference (const or non-const)
    foo(&c); // clearly mutable
I also believe the C++11 thing is outdated. Even when I still worked there some features were allowed from C++14 and some code was obviously going to be migrated to the C++14 equivalent once the issues with that were resolved (IIRC std::make_shared had an equivalent).
2 comments

I don't accept that any reasonable sized shop needs to subset C++ or insanity will prevail. Any particular slice of code needs to subset the language. You may have some perf sensitive code that can't afford virtual function overhead. Or some code that uses dynamically linked libraries for which RTTI may not work right (so you avoid RTTI there). Perhaps strict determinism is required and you can't use exceptions in this part of the code base.

However this is vastly different than saying that we don't want any of these features anywhere because they might not be appropriate under some conditions. I advocate education so developers can make decisions when to use and not to use certain features (same as selecting the right algorithm -- we don't ban binary search b/c it's harder to understand than linear search).

Same with the "we have tons of programmers" argument -- let's use the lowest common denominator (everything else is "fancy"/"clever") to make sure every line of code is understandable by anyone. Encourage people to learn, not everyone else to dumb down.

There's a very big C inherited footgun you can avoid with signed sizes: implicit conversions to unsigned on comparison.
GCC has had -Wsign-compare:

       -Wsign-compare
           Warn when a comparison between signed and unsigned values could
           produce an incorrect result when the signed value is converted to
           unsigned.  In C++, this warning is also enabled by -Wall.  In C, it
           is also enabled by -Wextra.
Since 1996. https://github.com/gcc-mirror/gcc/commit/de9554eb8ae74764555...

(And prior to that explicit option, it was just enabled as part of -Wextra/-W, from 1995: https://github.com/gcc-mirror/gcc/commit/7030c69607d547b3227... . For comparison, Google was founded in 1996.)

I buy that some of the integer promotion rules really suck, and Google's founders learned C prior to 1996. But the compiler has been able to warn us about this particular footgun for a long time.