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