Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Which C++ style guide do you follow?
49 points by ycombonator 15 days ago | hide | past | web | favorite | 45 comments
Options shamelessly copy-pasted from https://clang.llvm.org/

LLVM A style complying with the LLVM coding standards

Google A style complying with Google’s C++ style guide

Chromium A style complying with Chromium’s style guide

Mozilla A style complying with Mozilla’s style guide

WebKit A style complying with WebKit’s style guide




We follow Google's as good as we can. I think they have a stronger stance on some best practices which I personally don't agree with, but I also can't think of a better forcing function for less experienced C++ devs to write dangerous code and shoot themselves in the foot anyway.


While it's very popular, I find Google's to be the most distasteful. It's very opinionated in a very curmudgeonly kind of way.

In particular, the emphasis on 80 char wide lines hurts readability by encouraging shorter variable names and wastes quite a bit of vertical space. For example, this example line from the spec violates the spec: "using TimeSeries = std::unordered_set<DataPoint, std::hash<DataPoint>, DataPointComparator>;"

And it's strangely opinionated but in way that's particularly fearful of templates, macros, and SFINAE such that it causes more strife than it's worth. Like by forcing you to justify otherwise reasonable things like "template<typename Thing> RedisSerializeTheThing(const Thing& thing);" or "template<typename Thing> LexicalCastLoggerThatCanOptionallyTemplateSpecialize(const Thing& thing);"

Variadic templates fall under the template ban I guess and __VA_ARGS__ stuff is based around macros, so there's not really any good way under that standard to express something like a safer sprintf or tuple marshalling.

Essentially my problem with the guide is that it bans a lot of type-inference that makes C++ safer and faster. C++ is already dangerous, so I think that's the wrong choice.


The Google style guide developed over time through iterations involving several thousand programmers. It's the culmination of all those programmers and operational aspects which got it to this point. So when you say it's 'opinionated', the data has said the styling in the document is the right thing to do.


That's a funny way of putting it, almost like an appeal to tradition.

It reads more like Google had to herd a lot of junior programmers and rather than teaching better judgement or patterns, just walled off huge sections of the language completely.


Is there any other way at google scale?

I haven't written more than 100k LOC of C++ and yet there are already lots of code (mostly template meta programming) that I wrote that even I can't read anymore.

Now imagine blowing that up to (literally) billions of lines of C++ written by overly clever engineers all eager to prove themselves.


Quite a few things:

- Allow whatever C++ inside the project but force each project to export a plain C API and .so file. This has the quadruple bonus of (1) avoiding ABI problems between compilers, (2) hiding complexity from other teams, (3) forcing teams to think more about their APIs, and (4) being trivially callable from any other language.

- Large API/SPI review mailing lists. This worked quite well at Apple.

- Add a section to the style guide about what's appropriate template use and what's not. Banning one of the language's most important features is just a cop out.

- Better mentorship from senior engineers.


The template ban was made because they are Google, which already provides an internal high-quality fundamental C++ library so most people don't have to invent wheels


I think at work we use 120 char limit, with klang formatter making it so you don't have to think about it much.

80 seems excessive, but no limit means having to horizontal scroll or even resize windows in an aggravating way. Some sort of limit is a good thing. Vertical monitors can also be great, but are limited in horizontal space, making files with long lines a headache to read.

It also made reading code more consistently nice across different views, from diffs to review software.


Python's 79 columns is also insane. But at the same time, it's a weakly held opinion that's broadly overridden in the community. I think it's generally accepted as an obsolete idea.


Having shorter line lengths makes it easier to review diffs side by side (especially 3 way diffs).

The other thing that people do with long lines is that they try to combine a lot of statements per line. Then when that line has to be changed, it's harder to review in a diff (compared to the diff that affects a line containing a single statement).


In practice I just see it screwing up perfectly good lines way more often than long lines causing trouble.

This is one of those matter of opinion things. But it's so wildly one sided from my experience that I struggle to see the other side.


Perhaps one way to look at it is to compare long lines in code with long paragraphs in prose. I'm sure you've seen examples of posts on forums where someone writes a long post, but doesn't subdivide it into paragraphs. While it's possible to read and understand the message it's trying to convey, it's more difficult to do compared to a version that's divided into paragraphs.

Similarly, one can combine several statements in code on a single line, but that, in my opinion, is harder to read compared to having a single statement per line and harder to read the resulting diff when changing something in the line.

This is one example I copied from bashoneliners.com:

  man -k . | awk '{ print $1 " " $2 }' | dmenu -i -p man | awk '{ print $2 " " $1 }' | tr -d '()' | xargs man -t | ps2pdf - - | zathura -
Personally, I would find it easier to read and understand it if it was written as follows:

  man -k . \
  awk '{ print $1 " " $2 }' \
  dmenu -i -p man \
  awk '{ print $2 " " $1 }' \
  tr -d '()' \
  xargs man -t \
  ps2pdf - - \
  zathura -
If I had this in source control and decided to add, remove, or change one of the commands for this oneliner, then it would be far easier to read the diff if it was in the multi-line form compared to the single line form.


What do you mean by style? Whitespace and casing in names, chunks of the standard to use or not (unique_ptr, mutable refs as function arguments, auto), interface design paradigms (RAII, exceptions vs error codes, composition vs. inheritance)? It doesn't really change my answer (the Google style guide), but the reasons are somewhat different in each case. I choose Google's formatting basically because it meshes with the feature-set they recommend and their interface design philosophy. I choose the feature-set they recommend because their guide's coverage and reasoning are more comprehensive than those of comparable guides I've seen. I choose their interface design philosophy because it meshes with the feature-set and is better than trying to figure it out myself.

(I do work at google and got the "writes idiomatic c++" certification, but I'm writing the above from the perspective of the (very tiny amount of) c++ I write for personal projects, including things I worked on before I got past their interviews to get hired.)


Whatever clang-format and clang-tidy says! Seriously, using automated tools just takes away all of the bikeshedding revolving this issue.


What's the difference between clang-format and clang-tidy? Do they have different configuration options? I'm only using clang-format so far.


clang-format kinda does what it says - parses your code, then indents and spaces it according to the rules. It doesn't try to understand code intent, it just looks at syntax.

clang-tidy does some deeper inspection and can be used to flag things that are "bad practice", not just "bad formatting". There's a big list of checks here:

https://clang.llvm.org/extra/clang-tidy/checks/list.html

At a minimum, I like to enable all the `bugprone-*` tidy rules, they just seem sensible to turn on.

e.g. https://clang.llvm.org/extra/clang-tidy/checks/bugprone-stri...

You're able to run `clang-tidy -fix` to automate fixing of many of the things it will flag.


Google's style guide has been beaten in to me to get "C++ readability" at Google. Makes working on LLVM tough some times. .clang-format is a must for any project IMO.


I do not write C++ often as i'm not a fan of the language, but when i do... i don't follow any of these :-P. I have my own style which is pretty much an "evolution" of what i see a lot of C++ projects, mainly from the MSVC/Windows world, use.

In short, whitespace is mostly Allman style with spaces for indentation. Names use mostly CamelCase, with some exceptions. Public members go first, protected members go middle, private members go last.

Instance fields have an m_ prefix, static fields that have an s_ prefix and both use javaCase instead of CamelCase. Function parameters and local variables also use javaCase. In the cases where javaCase is used, whenever possible single word identifiers are used. Classes have a C prefix except mixings which have an M prefix and interfaces which have an I prefix, structs have an S prefix, enums have an E prefix, namespaces have an N prefix, templates have a T prefix (not C/S, etc), function types have an F prefix, typedefs meant for aliasing have an A prefix. Exported/imported global variables have a G prefix, static toplevel variables have an L prefix. Macros all in all caps with underscores separating words. Pointer and reference declarations have the start/ampersand right after the type name, whenever possible there is a single declaration per line and only a single pointer/reference use (using aliases for more complex stuff). All types are declared in the global namespace, however functions are grouped in topic-specific namespaces. When inheriting a class and overriding virtual methods, the overrides are declared in a separate block in the class with the comment "// Baseclass methods" or something like that. Other members have a single line documenting their purpose (no doxygen, plain text, i find doxygen comments to be noise, if there is need for explicit documentation it should be in a separate file).

There are other minor things, like how header files are laid out, "getter" functions that only return a private/protected member being inlined, etc but the above are the main stuff. I do not have any of these rules written out anywhere, i just happen to "grow" to write C++ code like that over time. Interestingly my C code style is totally different (snake_case, _t suffix for types, _s suffix for structs, etc).

Here is an example:

https://pastebin.com/anLvHRQ2

It is the model document (as in document/view) for the mesh editor in this video:

https://www.youtube.com/watch?v=rr1Sr9hTkzg


This is how a huge chunk of the Windows or Windows-trained world writes C++. You don't have to like it but it's recognizable and common.


Yes, especially the m_, I, C, S, E and G stuff are very common. I think it comes from MFC. The T stuff is less common - in my current company templates are also C-prefix, but in the previous company i worked at they were T-prefixed.

Some other stuff like L, F, A, s_, etc are things i came up with myself for my own code (for work code i use whatever others are using) since i didn't like the more common uses (in the previous company i worked at statics were also S prefixed, but i wanted something to separate from structs so i used L for "local"). Of course once you get used to the common style above, these "extensions" are mostly obvious so i'm certain that others are using them too.


Is there a style guide for using exceptions in code that people like? (at the time I'm writing this there is a lot of pro google style guide, which is great in my opinion except for their no-exceptions approach)


I use Google's, but don't follow it to the word. I use their linter with couple of my own rules related to C++11 headers (chrono, etc), lines width, whitespaces, etc.

But in general, I try to follow good practices from it like: namespace formatting, as well as anonymous/unnamed namespaces, names and order of includes, #define guard (although I prefer #pragma once), use of smart pointers (fixed owners for dynamically allocated objects), explicit constructors, etc.


Unfortunately lot of these guidelines are incompatible to each other. Many have certain rules just because of legacy they had inherited (for ex, Google) and you are much better off ignoring those rules. After spending too much time on this, I use this for my projects:

https://microsoft.github.io/AirSim/docs/coding_guidelines/


  $ cat ~/.clang-format
  ---
  BreakStringLiterals: 'false'
  ColumnLimit: '0'
  IndentWidth: '4'
  ObjCBlockIndentWidth: '4'
  ObjCSpaceBeforeProtocolList: 'false'
  PenaltyBreakComment: '0'
  SortIncludes: 'true'
  TabWidth: '4'
  UseTab: ForIndentation
  
  ...
Otherwise, whatever the project I'm working on uses.


Google's style-guide, but prefering references over raw ptrs and using SNAKE_CASE_CAPS for constants instead of 'kSnakeCaseCaps'


> prefering references over raw ptrs and using

I started my career doing C++ at Google, so for those engineering habits that I haven't thought through or otherwise have a strong opinion about, my defaults are in line with the GSG. But avoiding non-const references is something that I find myself in pretty strong agreement with, as part of a coding style that makes function signatures for complex logic as simple and comprehensible as possible. I'd be interested in hearing the perspective behind your reasoning otherwise. Is it mainly for the ability to signal non-nullability in the signature?


> Is it mainly for the ability to signal non-nullability in the signature?

Can't answer for the parent, but for me yes it's exactly that.

When I'm calling a function I'm going to look up the prototype anyways so I don't really care whether it's taking a reference or a pointer.

When I'm implementing the function, I want to make sure that all my callers never pass me a nullptr. Because of the styleguide I'm forced to put a "DCHECK(ptr);" and add a comment in the prototype saying "|ptr| must not be null".


Last time we needed one we chose google. Not because we necessarily liked it but because then there was no argument about what the guide is or should be and so we didn’t spend any time writing one.

It’s ok, not great, and definitely google specific (e.g. even google would prefer to use exceptions but for legacy reasons they can’t. So we couldn’t either)


Was there a reason you couldn't use GSG but change the section on exceptions? I don't think there are any logical dependencies between the exception ban and other parts of the style guide, but I could be mistaken. Every company I've worked at since starting at Google uses the GSG, so I've never had occasion to learn how to use exceptions in C++.


Yes there was a reason: once you change one thing you open everything else up for discussion as well. And while that would probably lead to a better guide (for us) than Google's, the time and thought involved in that would take away from solving the problems we wanted to solve in the first place.


Hm yea, I figured that might be the case, but to me, the "this is only for legacy purposes" claim stands out enough from the rest of the GSG that I figured it would be easy to separate it from the rest of the guide. I obviously don't know the dynamics of your team though and totally find your explanation plausible.


I use Chromium style[1], worked out well. Have to check my notes on PC why I picked that.

[1]: https://github.com/dmsurti/AssimpKit/blob/master/.clang-form...


We more-or-less use Google's. Formatting level style is enforced via clang-format + CI.




Google and Chromium are extremely similar. Very very minor differences.



Sanity check for any whitespace style guides....

If you're not prepare to wire an auto-indent into every ones commit hooks....

....you're just not serious are you?

Bottom Line on White space....

Have some.

Be mostly consistent.


Google's, but clang-format does most of the work. I used it for so long that I now get nervous whenever I see a non-const reference somewhere :)


Game studio, 80+ people writing C++ and Lua, we use Google’s style guide.


Curious, do you guys use an engine (unreal, unity, godot, etc) or something in-house?


We use Unreal Engine extensively for multiple projects.

Some of my colleagues are also developing a voxel game engine for another game.

And we have also used Lua LÖVE multiple times during our yearly hackatons.


Cool. Thanks. So I take it you primarily write code leveraging the Unreal engine but the point-n-click functionality of the Unreal editor is more utilized by people doing the world design and artists?

I've explored Unity a small amount but I was really turned off by the overly simplistic approach to game development. The whole scene-first approach where you'd just drag in your hero object, set some attributes, drag and drop some enemy objects, etc. It reminded me heavily of Flash game development 15 years ago.


The editor is used by design and art lots, bit lots of programming in UE4 involves exposing controls for people who are using the things you write. There's also blueprint which is a visual scripting language which you can use for behaviour.

I think tarring unity as overly simplistic is unfair. Unity let's you write code ( in as a game object) and use them, it's not really drag and drop.

(Disclaimer: I work in games, for Epic)


LLVM




Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: