-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
doc: add basic C++ style guide #16090
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a4417a5
39ab867
b6a028c
66a546d
68176fe
8b289f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| # C++ Style Guide | ||
|
|
||
| Unfortunately, the C++ linter (based on | ||
| [Google’s `cpplint`](https://github.com/google/styleguide)), which can be run | ||
| explicitly via `make lint-cpp`, does not currently catch a lot of rules that are | ||
| specific to the Node.js C++ code base. This document explains the most common of | ||
| these rules: | ||
|
|
||
| ## Left-leaning (C++ style) asterisks for pointer declarations | ||
|
|
||
| `char* buffer;` instead of `char *buffer;` | ||
|
|
||
| ## 2 spaces of indentation for blocks or bodies of conditionals | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also for loops (unless conditionals includes loops). Now that I am thinking about it, I am not sure we use loops without parens...
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, conditionals includes conditional loops. :) Anyway, I don’t think the current phrasing leaves anybody thinking that we use indentation other than 2 spaces. |
||
|
|
||
| ```c++ | ||
| if (foo) | ||
| bar(); | ||
| ``` | ||
|
|
||
| or | ||
|
|
||
| ```c++ | ||
| if (foo) { | ||
| bar(); | ||
| baz(); | ||
| } | ||
| ``` | ||
|
|
||
| Braces are optional if the statement body only has one line. | ||
|
|
||
| `namespace`s receive no indentation on their own. | ||
|
|
||
| ## 4 spaces of indentation for statement continuations | ||
|
|
||
| ```c++ | ||
| VeryLongTypeName very_long_result = SomeValueWithAVeryLongName + | ||
| SomeOtherValueWithAVeryLongName; | ||
|
||
| ``` | ||
|
|
||
| Operators are before the line break in these cases. | ||
|
|
||
| ## Align function arguments vertically | ||
|
|
||
| ```c++ | ||
| void FunctionWithAVeryLongName(int parameter_with_a_very_long_name, | ||
| double other_parameter_with_a_very_long_name, | ||
| ...); | ||
| ``` | ||
|
|
||
| If that doesn’t work, break after the `(` and use 4 spaces of indentation: | ||
|
|
||
| ```c++ | ||
| void FunctionWithAReallyReallyReallyLongNameSeriouslyStopIt( | ||
| int okay_there_is_no_space_left_in_the_previous_line, | ||
| ...); | ||
| ``` | ||
|
|
||
| ## Initialization lists | ||
|
|
||
| Long initialization lists are formatted like this: | ||
|
|
||
| ```c++ | ||
| HandleWrap::HandleWrap(Environment* env, | ||
| Local<Object> object, | ||
| uv_handle_t* handle, | ||
| AsyncWrap::ProviderType provider) | ||
| : AsyncWrap(env, object, provider), | ||
| state_(kInitialized), | ||
| handle_(handle) { | ||
| ``` | ||
|
|
||
| ## CamelCase for methods, functions and classes | ||
|
|
||
| Exceptions are simple getters/setters, which are named `property_name()` and | ||
| `set_property_name()`, respectively. | ||
|
|
||
| ```c++ | ||
| class FooBar { | ||
| public: | ||
| void DoSomething(); | ||
| static void DoSomethingButItsStaticInstead(); | ||
|
||
|
|
||
| void set_foo_flag(int flag_value); | ||
| int foo_flag() const; // Use const-correctness whenever possible. | ||
| }; | ||
| ``` | ||
|
|
||
| ## snake\_case for local variables and parameters | ||
|
|
||
| ```c++ | ||
| int FunctionThatDoesSomething(const char* important_string) { | ||
| const char* pointer_into_string = important_string; | ||
| } | ||
| ``` | ||
|
|
||
| ## snake\_case\_ for private class fields | ||
|
|
||
| ```c++ | ||
| class Foo { | ||
| private: | ||
| int counter_ = 0; | ||
| }; | ||
| ``` | ||
|
|
||
| ## Space after `template` | ||
|
|
||
| ```c++ | ||
| template <typename T> | ||
| class FancyContainer { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
|
||
| ## Type casting | ||
|
|
||
| - Always avoid C-style casts (`(type)value`) | ||
| - `dynamic_cast` does not work because RTTI is not enabled | ||
| - Use `static_cast` for casting whenever it works | ||
| - `reinterpret_cast` is okay if `static_cast` is not appropriate | ||
|
||
|
|
||
| ## Memory allocation | ||
|
||
|
|
||
| - `Malloc()`, `Calloc()`, etc. from `util.h` abort in Out-of-Memory situations | ||
| - `UncheckedMalloc()`, etc. return `nullptr` in OOM situations | ||
|
|
||
| ## `nullptr` instead of `NULL` or `0` | ||
|
|
||
| What it says in the title. | ||
|
|
||
| ## Avoid throwing JavaScript errors in nested C++ methods | ||
|
|
||
| If you need to throw JavaScript errors from a C++ binding method, try to do it | ||
| at the top level and not inside of nested calls. | ||
|
|
||
| A lot of code inside Node.js is written so that typechecking etc. is performed | ||
| in JavaScript. | ||
|
|
||
| Using C++ `throw` is not allowed. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No doubt this is correct, but it always bothers me with multiple variables:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just declare one variable per line