My recent post about Google’s C++ style guide attracted some great comments. Billy O’Neal corrected my ignorance about C++ formatting tools by alerting me to the existence of clang-format; John Payson came up with a way of getting piecemeal from the “no exceptions allowed” state to the “exceptions allowed and all code able to handle them” state, and Titus Winters (a maintainer of the Google style guide) mentioned a talk he gave at CppCon on the subject.
The talk is on YouTube here, and is worth watching in its entirety, but here are a few highlights I took away from it:
|1:42||“How should we format our code? BORING QUESTION!”. Titus introduces clang-format.|
|3:14||What is the purpose of a style guide?|
|5:15||Google’s publicly available style guide is “probably optimizing for a different set of values than your organization needs”|
|6:48||Google has an indexer – Kythe – which should be available as open source soon.|
|9:39||Google plan to be around for at least 10 years. Almost everywhere I have worked has assumed that they are going to be around for 10 years (and several of those places went bust a long time short of 10 years), but very few of my employers have made long term decisions about their code – they might have assumed that they will be around for 10 years but on the code side they certainly didn’t plan for it.|
|10:55||The philosophies of the style guide.|
|14:45||A future version of the style guide will allow streams.|
|28:10||“No non-const references as function arguments” is one of the most controversial rules in the style guide. I am not surprised by this, but I am disappointed. The arguments in favour of no non-const references always seemed good to me.|
|38:25||“I don’t care about throwing out of memory exceptions”. There are certainly products where an out of memory exception just translates to “die instantly”, however that isn’t universally true. I have never worked on a project that was able to recover and continue after running out of memory but I have worked on products that have wanted to know about the out of memory case so they can save the data the user is working on. It’s just another reminder that guidelines depend on the products they are being used for.|
|57:20||Probably the best answer to any formatting question that I have heard.Q: What about tabs vs. spaces? What’s Google’s take on that?A: I don’t care … I just use clang-format|
The theme of the day is clang-format. I spent some time over the weekend playing around with clang-format and it is excellent. I haven’t worked out how to get it to do quite everything I want, however the consistency benefits far outweigh any minor deviations from my preferred style. Also, if it bothers me that much I have the source code and can add more options.
On a related note, this is the first time I have been able to get Clang and LLVM (mostly) compiling on Windows without spending a ridiculous amount of time on it. Windows has long been the afterthought platform for LLVM and Clang – it looks like it’s getting better.
4 thoughts on “Google’s C++ style guide – follow up”
Regarding: “I don’t care about throwing out of memory exceptions”
Well, C++ doesn’t have an “out of memory” exception. It has an allocation failure exception.
To me, that’s always been an important distinction. Actually being out of free memory is extremely rare, but it’s only one possible cause of an allocation failure.
A far more common cause is fragmentation: where there is still free memory, but not in one contiguous chunk that can satisfy the request. In 64-bit server software running on a virtual memory machine, even this is hugely unlikely. But in any sort of client context, like a smartphone app, it’s a real concern.
When you’re a server that’s truly out-of-memory, you probably are in a really bad state and there may not be a reasonable alternative to terminating. But if you’ve got a fragmentation problem in a client-side app, you probably shouldn’t crash just because you can’t allocate enough memory for a purely-decorative bitmap for the UI.
Given that Google is doing more and more on the client side (Android, apps, Chrome, etc.), they’re going to have to start caring about allocation failures. If there’s going to be one style guide to rule them all, it’s going to have to change.
Good point. I will fess up to using incorrect terminology here. On a 32 bit system the problem is not necessarily “out of physical memory” but “out of address space”. I have been tripped up by that several times in the past. I am curious to see whether we ever run into problems with a 64 bit address space. It seems that 18,446,744,073,709,551,616 bytes of memory should be enough for anybody.
I’ve worked in projects where different containers and allocator-aware classes would use different heaps, pools, shared memory segments, etc. Allocation failure meant different things in different cases, but terminating the service wasn’t an option. And that’s only one small class of situations where exceptions are indispensable.
I was a little disappointed in the talk for other reasons, I find many other parts of the guide to be equally or more controversial.
There are a number of ways in which I think C++ is too complicated; on the other hand, it has a number of features which good languages and frameworks should have, but which are missing in Java, C#, and other .NET languages. I think Swift takes some steps in the right direction, but makes a few missteps as well.
One of the major difference between C++ and the other languages/frameworks is the behavior of virtual members during object construction. Proponents of each style complain about the other, but I would suggest that in a well-designed language/framework, the issue should be moot. Object construction should be split into two phases; during the first phase, each layer would be expected to construct itself sufficiently to make virtual methods usable, but not to call them nor expose the object under construction to outside code. Since each derived class would have a chance to set itself up to handle virtual method calls before the start of the second phase, the second phase would allow methods at any level to expose the object under construction or call virtual methods as they saw fit (subject to any inheritance contract specified by the base class). Too bad different factions in the language wars seem more interested in arguing about how the other side’s way of doing something is evil, rather than recognizing that in many cases both side’s ways are equally evil, but are rendered necessary by what should be correctable deficiencies in the language they’re using.
Consider the behavior of unsigned integers. Many people regard unsigned integers as “evil” because their semantics are a weird hybrid of what should be distinct types. Imagine that a language were to define three different four-byte types of unsigned integer: UWrap32, UNum32, and UNum31 [and likewise for every other size, except that there would be no UNum64] with the following semantics: Values of type UWrapXX would never be promoted; an operation between e.g. a UWrap16 and an Int64 would yield type UWrap16, and arithmetic between mixed sixes of UWrap would be forbidden. Operations on all other “unsigned number” types would yield the same result as if the values were promoted to Int64. A UNum31 would behave like an Int32 but with a compiler-enforced invariant that the value could not be negative. The only types where anything resembling integer overflow would be expected not to trap would be the UWrap types [and possibly SWrap types which would implement two’s-complement wrapping behavior].
If, rather than arguing about how unsigned types should behave, language implementers would separate out types that should behave like numbers and those which should behave like wrapping algebraic rings, then unsigned numbers could become a very useful language feature, rather than a source of annoyance and portability headaches. Unfortunately, I have no idea how to promote the idea to anyone who might be designing the next popular language.