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