Mercurial > template
annotate STYLE_CPP.md @ 10:eaae1fcabca8
Update braces style
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 09 Jun 2017 09:18:57 +0200 |
parents | ee0ef058cb94 |
children | e4fd9e7bf69a |
rev | line source |
---|---|
0 | 1 PROJECT NAME C++ CODING STYLE |
2 ============================= | |
3 | |
4 Style | |
5 ----- | |
6 | |
7 - Always use 4 spaces as indentation, | |
9
ee0ef058cb94
Add note about UTF-8 / LF
David Demelier <markand@malikania.fr>
parents:
8
diff
changeset
|
8 - Use UTF-8 charset, |
ee0ef058cb94
Add note about UTF-8 / LF
David Demelier <markand@malikania.fr>
parents:
8
diff
changeset
|
9 - Use Unix line endings, |
0 | 10 - Do not exceed 120 characters for lines of code, |
11 - Do not exceed 80 characters for comments, | |
12 - Never write two blank consecutives blank lines, | |
7
4fcd920b1a02
Add note about bad words
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
13 - Do not use bad words. |
0 | 14 |
15 ### Braces | |
16 | |
17 Braces follow the K&R style, they are never placed on their own lines except for | |
18 function definitions. | |
19 | |
10 | 20 Do not put braces for single line statements except for clarity. |
0 | 21 |
22 if (condition) { | |
23 apply(); | |
24 add(); | |
10 | 25 } else |
0 | 26 ok(); |
10 | 27 |
28 if (condition) | |
29 validate(); | |
30 | |
31 if (foo) { | |
32 state = long + conditional + that + requires + several + lines + | |
33 to + complete; | |
0 | 34 } |
35 | |
10 | 36 Functions require braces on their own lines. |
37 | |
38 void function() | |
39 { | |
0 | 40 } |
41 | |
42 And a lambda has its braces on the same lines too: | |
43 | |
44 sort([&] (object&) { | |
45 return true; | |
46 }); | |
47 | |
48 ### Spaces | |
49 | |
50 Each reserved keyword (e.g. `if`, `for`, `while`) requires a single space before | |
51 its argument. | |
52 | |
53 Normal function calls do not require it. | |
54 | |
55 if (foo) { | |
56 destroy(sizeof (int)); | |
57 } | |
58 | |
59 ### References and pointers | |
60 | |
61 References and pointers are always next to the type name and not the variable. | |
62 | |
63 T& get(const std::string& name); | |
64 | |
65 int* p = &x; | |
66 | |
67 ### Naming | |
68 | |
69 - English names, | |
8
d7cbb9a40f0d
Member variables are now named like_this_
David Demelier <markand@malikania.fr>
parents:
7
diff
changeset
|
70 - Member variables have trailing underscore (e.g foo\_bar\_), |
0 | 71 - No hungarian notation. |
72 | |
73 Everything is in `underscore_case` except template parameters and macros. | |
74 | |
75 #if defined(FOO) | |
76 # include <foo.hpp> | |
77 #endif | |
78 | |
79 namespace baz { | |
80 | |
81 class object { | |
82 private: | |
8
d7cbb9a40f0d
Member variables are now named like_this_
David Demelier <markand@malikania.fr>
parents:
7
diff
changeset
|
83 std::string name_; |
0 | 84 |
85 public: | |
86 inline const std::string& name() const noexcept | |
87 { | |
8
d7cbb9a40f0d
Member variables are now named like_this_
David Demelier <markand@malikania.fr>
parents:
7
diff
changeset
|
88 return name_; |
0 | 89 } |
90 }; | |
91 | |
92 template <typename Archive> | |
93 void open(const Archive& ar) | |
94 { | |
95 bool is_valid = false; | |
96 } | |
97 | |
98 } // !baz | |
99 | |
100 ### Header guards | |
101 | |
102 Do not use `#pragma once`. | |
103 | |
104 Header guards are usually named **PROJECT_COMPONENT_FILENAME_HPP**. | |
105 | |
106 #ifndef FOO_COMMON_UTIL_HPP | |
107 #define FOO_COMMON_UTIL_HPP | |
108 | |
109 #endif // !FOO_COMMON_UTIL_HPP | |
110 | |
111 ### Enums | |
112 | |
113 Enumerations constants are always defined in separate line to allow commenting | |
114 them as doxygen. | |
115 | |
116 Enum class are encouraged. | |
117 | |
118 enum class color { | |
119 blue, | |
120 red, | |
121 green | |
122 }; | |
123 | |
124 ### Files | |
125 | |
126 - Use `.cpp` and `.hpp` as file extensions, | |
127 - Filenames are all lowercase. | |
128 | |
129 ### Comments | |
130 | |
131 Avoid useless comments in source files. Comment complex things or why it is done | |
132 like this. However any public function in the .hpp **must** be documented as | |
133 doxygen without exception. | |
134 | |
135 /* | |
136 * Multi line comments look like | |
137 * this. | |
138 */ | |
139 | |
140 // Short comment | |
141 | |
2 | 142 Use `#if 0` to comment blocks of code. |
143 | |
144 #if 0 | |
145 broken_stuff(); | |
146 #endif | |
147 | |
0 | 148 ### Includes |
149 | |
150 The includes should always come in the following order. | |
151 | |
152 1. C++ headers | |
153 2. C header | |
154 3. Third party libraries | |
155 4. Application headers in "" | |
156 | |
157 #include <cstring> | |
158 #include <cerrno> | |
159 | |
160 #include <sys/stat.h> | |
161 | |
162 #include <libircclient.h> | |
163 | |
164 #include "foo.h" | |
165 | |
166 **Note**: always use C++ headers for C equivalent, stdio.h -> cstdio, etc. | |
167 | |
168 ### Commit messages | |
169 | |
170 Commit messages are written using the following syntax: | |
171 | |
172 Topic: short message less than 80 characters | |
173 | |
174 Optional additional description if needed. | |
175 | |
176 Replace `Topic` with one of the following: | |
177 | |
178 - **CMake**: for the build system, | |
179 - **Docs**: for the documentation, | |
180 - **Misc**: for miscellaneous files, | |
3 | 181 - **Tests**: for the unit tests. |
0 | 182 |
183 Programming | |
184 ----------- | |
185 | |
186 ### C language | |
187 | |
188 Do not use old C stuff like `void *`, `srand/rand`, `printf` or anything that | |
189 can be rewritten in modern C++. | |
190 | |
191 ### RTTI | |
192 | |
193 Usage of `dynamic_cast` and `typeid` are completely disallowed in any shape of | |
194 form. | |
195 | |
196 ### Arguments | |
197 | |
198 It is recommended to pass parameters by value or const reference. Usage of | |
199 non-const reference as output parameter is **discouraged** and should be avoided | |
200 in many case because it does not allow chaining of expressions like: | |
201 | |
202 std::cout << reverse(upper(clean(" hello world! "))) << std::endl; | |
203 | |
204 If your function is designed to return a modified value passed as argument, it | |
205 is better to take it by value and modify it directly. | |
206 | |
207 std::string clean(std::string input) | |
208 { | |
209 if (!input.empty() && input.back() == '\r') { | |
210 input.pop_back(); | |
211 } | |
212 | |
213 return input; | |
214 } | |
215 | |
216 Never pass primitive types as const value. | |
217 | |
218 ### Assertions | |
219 | |
220 Use the `assert` macro from the cassert header file to verify programming | |
221 errors. | |
222 | |
223 For example, you may use `assert` to verify that the developer access the data | |
224 between the bounds of an array: | |
225 | |
226 T& operator[](unsigned index) | |
227 { | |
8
d7cbb9a40f0d
Member variables are now named like_this_
David Demelier <markand@malikania.fr>
parents:
7
diff
changeset
|
228 assert(index < length_); |
0 | 229 |
8
d7cbb9a40f0d
Member variables are now named like_this_
David Demelier <markand@malikania.fr>
parents:
7
diff
changeset
|
230 return data_[index]; |
0 | 231 } |
232 | |
233 The `assert` macro is not meant to check that a function succeeded, this code | |
234 must not be written that way: | |
235 | |
236 assert(listen(10)); | |
237 | |
238 ### Exceptions | |
239 | |
240 You must use exceptions to indicate an error that was unexpected such as: | |
241 | |
242 - Failing to open a file, | |
243 - I/O unexpected errors, | |
244 - Parsing errors, | |
245 - User errors. | |
246 | |
247 You may use the C++ standard exceptions defined in the stdexcept header but if | |
248 you need to carry more data within your exception, you should derive from | |
249 `std::exception`. | |
250 | |
251 ### Free functions | |
252 | |
253 Basic utility functions should be defined in a namespace as a free function not | |
254 as a static member function, we're doing C++ not Java. | |
255 | |
256 Example: | |
257 | |
258 namespace util { | |
259 | |
260 std::string clean(std::string input); | |
261 | |
262 } // !util | |
263 | |
264 ### Variables initialization | |
265 | |
266 Use parentheses to initialize non primitive types: | |
267 | |
268 throw std::runtime_error("foo"); | |
269 | |
270 my_class obj("bar"); | |
271 | |
272 Use brace initialization when you want to use an initializer list, type | |
273 elision: | |
274 | |
275 std::vector<int> v{1, 2, 3}; | |
276 | |
277 foo({1, 2}); // type deduced | |
278 | |
279 return { "true", false }; // std::pair returned | |
280 | |
281 Use the assignment for primitive types: | |
282 | |
283 int x = 123; | |
284 bool is_valid = true; | |
285 | |
286 ### Classes | |
287 | |
288 Classes are usually defined in the following order: | |
289 | |
290 1. Public inner types (enums, classes), | |
291 2. Protected/private members | |
292 3. Public functions | |
293 | |
294 class foo { | |
295 public: | |
296 enum class type { | |
297 a, | |
298 b | |
299 }; | |
300 | |
301 private: | |
8
d7cbb9a40f0d
Member variables are now named like_this_
David Demelier <markand@malikania.fr>
parents:
7
diff
changeset
|
302 int member_{0}; |
0 | 303 |
304 public: | |
305 void some_function(); | |
306 } | |
307 | |
308 ### Structs | |
309 | |
310 Do not use C structs unless you have very good reason to do so. If you want to | |
311 pack some data, just use `class` and make all fields public. | |
312 | |
313 class point { | |
314 public: | |
6
41dac98beeb2
Use inclass initializers
David Demelier <markand@malikania.fr>
parents:
3
diff
changeset
|
315 int x{0}; |
41dac98beeb2
Use inclass initializers
David Demelier <markand@malikania.fr>
parents:
3
diff
changeset
|
316 int y{0}; |
0 | 317 }; |
318 | |
319 ### Return | |
320 | |
321 The preferred style is to return early in case of errors. That makes the code | |
322 more linear and not highly indented. | |
323 | |
324 This code is preferred: | |
325 | |
326 if (a_condition_is_not_valid) { | |
327 return nullptr; | |
1
9bf9b4634339
Update return statement
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
328 } |
9bf9b4634339
Update return statement
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
329 if (an_other_condition) { |
0 | 330 return nullptr; |
331 } | |
332 | |
333 auto x = std::make_shared<object>(); | |
334 | |
335 x->start(); | |
336 x->save(); | |
337 | |
338 return x; | |
339 | |
1
9bf9b4634339
Update return statement
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
340 Additional rules: |
9bf9b4634339
Update return statement
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
341 |
9bf9b4634339
Update return statement
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
342 - Do never put parentheses between the returned value, |
9bf9b4634339
Update return statement
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
343 - Do not put a else branch after a return. |