Skip to content

Commit 23340b9

Browse files
committed
doc: add basic C++ style guide
Ideally, most of these things would be enforced via linter rules. This is a first step into having a style guide that goes beyond what the linter currently enforces. PR-URL: #16090 Fixes: #12636 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent f4cab35 commit 23340b9

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

CONTRIBUTING.md

+3
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ should follow the [Style Guide](doc/STYLE_GUIDE.md). Code samples included
282282
in the API docs will also be checked when running `make lint` (or
283283
`vcbuild.bat lint` on Windows).
284284

285+
For contributing C++ code, you may want to look at the
286+
[C++ Style Guide](CPP_STYLE_GUIDE.md).
287+
285288
#### Step 4: Commit
286289

287290
It is a recommended best practice to keep your changes as logically grouped

CPP_STYLE_GUIDE.md

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# C++ Style Guide
2+
3+
Unfortunately, the C++ linter (based on
4+
[Google’s `cpplint`](https://github.com/google/styleguide)), which can be run
5+
explicitly via `make lint-cpp`, does not currently catch a lot of rules that are
6+
specific to the Node.js C++ code base. This document explains the most common of
7+
these rules:
8+
9+
## Left-leaning (C++ style) asterisks for pointer declarations
10+
11+
`char* buffer;` instead of `char *buffer;`
12+
13+
## 2 spaces of indentation for blocks or bodies of conditionals
14+
15+
```c++
16+
if (foo)
17+
bar();
18+
```
19+
20+
or
21+
22+
```c++
23+
if (foo) {
24+
bar();
25+
baz();
26+
}
27+
```
28+
29+
Braces are optional if the statement body only has one line.
30+
31+
`namespace`s receive no indentation on their own.
32+
33+
## 4 spaces of indentation for statement continuations
34+
35+
```c++
36+
VeryLongTypeName very_long_result = SomeValueWithAVeryLongName +
37+
SomeOtherValueWithAVeryLongName;
38+
```
39+
40+
Operators are before the line break in these cases.
41+
42+
## Align function arguments vertically
43+
44+
```c++
45+
void FunctionWithAVeryLongName(int parameter_with_a_very_long_name,
46+
double other_parameter_with_a_very_long_name,
47+
...);
48+
```
49+
50+
If that doesn’t work, break after the `(` and use 4 spaces of indentation:
51+
52+
```c++
53+
void FunctionWithAReallyReallyReallyLongNameSeriouslyStopIt(
54+
int okay_there_is_no_space_left_in_the_previous_line,
55+
...);
56+
```
57+
58+
## Initialization lists
59+
60+
Long initialization lists are formatted like this:
61+
62+
```c++
63+
HandleWrap::HandleWrap(Environment* env,
64+
Local<Object> object,
65+
uv_handle_t* handle,
66+
AsyncWrap::ProviderType provider)
67+
: AsyncWrap(env, object, provider),
68+
state_(kInitialized),
69+
handle_(handle) {
70+
```
71+
72+
## CamelCase for methods, functions and classes
73+
74+
Exceptions are simple getters/setters, which are named `property_name()` and
75+
`set_property_name()`, respectively.
76+
77+
```c++
78+
class FooBar {
79+
public:
80+
void DoSomething();
81+
static void DoSomethingButItsStaticInstead();
82+
83+
void set_foo_flag(int flag_value);
84+
int foo_flag() const; // Use const-correctness whenever possible.
85+
};
86+
```
87+
88+
## snake\_case for local variables and parameters
89+
90+
```c++
91+
int FunctionThatDoesSomething(const char* important_string) {
92+
const char* pointer_into_string = important_string;
93+
}
94+
```
95+
96+
## snake\_case\_ for private class fields
97+
98+
```c++
99+
class Foo {
100+
private:
101+
int counter_ = 0;
102+
};
103+
```
104+
105+
## Space after `template`
106+
107+
```c++
108+
template <typename T>
109+
class FancyContainer {
110+
...
111+
}
112+
```
113+
114+
## Type casting
115+
116+
- Always avoid C-style casts (`(type)value`)
117+
- `dynamic_cast` does not work because RTTI is not enabled
118+
- Use `static_cast` for casting whenever it works
119+
- `reinterpret_cast` is okay if `static_cast` is not appropriate
120+
121+
## Memory allocation
122+
123+
- `Malloc()`, `Calloc()`, etc. from `util.h` abort in Out-of-Memory situations
124+
- `UncheckedMalloc()`, etc. return `nullptr` in OOM situations
125+
126+
## `nullptr` instead of `NULL` or `0`
127+
128+
What it says in the title.
129+
130+
## Avoid throwing JavaScript errors in nested C++ methods
131+
132+
If you need to throw JavaScript errors from a C++ binding method, try to do it
133+
at the top level and not inside of nested calls.
134+
135+
A lot of code inside Node.js is written so that typechecking etc. is performed
136+
in JavaScript.
137+
138+
Using C++ `throw` is not allowed.

0 commit comments

Comments
 (0)