Serenity Operating System
1# Serenity C++ coding style
2
3For low-level styling (spaces, parentheses, brace placement, etc), all code should follow the format specified in `.clang-format` in the project root.
4
5**Important: Make sure you use `clang-format` version 8 or later!**
6
7This document describes the coding style used for C++ code in the Serenity Operating System project. All new code should conform to this style.
8
9We'll definitely be tweaking and amending this over time, so let's consider it a living document. :)
10
11
12### Names
13
14[](#names-basic) A combination of CamelCase and snake\_case. Use CamelCase (Capitalize the first letter, including all letters in an acronym) in a class, struct, or namespace name. Use snake\_case (all lowercase, with underscores separating words) for variable and function names.
15
16###### Right:
17
18```cpp
19struct Entry;
20size_t buffer_size;
21class FileDescriptor;
22String absolute_path();
23```
24
25###### Wrong:
26
27```cpp
28struct data;
29size_t bufferSize;
30class Filedescriptor;
31String MIME_Type();
32```
33
34[](#names-full-words) Use full words, except in the rare case where an abbreviation would be more canonical and easier to understand.
35
36###### Right:
37
38```cpp
39size_t character_size;
40size_t length;
41short tab_index; // More canonical.
42```
43
44###### Wrong:
45
46```cpp
47size_t char_size;
48size_t len;
49short tabulation_index; // Goofy.
50```
51
52[](#names-data-members) Data members in C++ classes should be private. Static data members should be prefixed by "s\_". Other data members should be prefixed by "m\_". Global variables should be prefixed by "g\_".
53
54###### Right:
55
56```cpp
57class String {
58public:
59 ...
60
61private:
62 int m_length { 0 };
63};
64```
65
66###### Wrong:
67
68```cpp
69class String {
70public:
71 ...
72
73 int length { 0 };
74};
75```
76
77[](#names-setter-getter) Precede setters with the word "set". Use bare words for getters. Setter and getter names should match the names of the variables being set/gotten.
78
79###### Right:
80
81```cpp
82void set_count(int); // Sets m_count.
83int count() const; // Returns m_count.
84```
85
86###### Wrong:
87
88```cpp
89void set_count(int); // Sets m_the_count.
90int get_count() const; // Returns m_the_count.
91```
92
93[](#names-out-argument) Precede getters that return values through out arguments with the word "get".
94
95###### Right:
96
97```cpp
98void get_filename_and_inode_id(String&, InodeIdentifier&) const;
99```
100
101###### Wrong:
102
103```cpp
104void filename_and_inode_id(String&, InodeIdentifier&) const;
105```
106
107[](#names-verb) Use descriptive verbs in function names.
108
109###### Right:
110
111```cpp
112bool convert_to_ascii(short*, size_t);
113```
114
115###### Wrong:
116
117```cpp
118bool to_ascii(short*, size_t);
119```
120
121[](#names-if-exists) When there are two getters for a variable, and one of them automatically makes sure the requested object is instantiated, prefix that getter function which with `ensure_`. As it ensures that an object is created, it should consequently also return a reference, not a pointer.
122
123###### Right:
124
125```cpp
126Inode* inode();
127Inode& ensure_inode();
128```
129
130###### Wrong:
131
132```cpp
133Inode& inode();
134Inode* ensure_inode();
135```
136
137[](#names-variable-name-in-function-decl) Leave meaningless variable names out of function declarations. A good rule of thumb is if the parameter type name contains the parameter name (without trailing numbers or pluralization), then the parameter name isn't needed. Usually, there should be a parameter name for bools, strings, and numerical types.
138
139###### Right:
140
141```cpp
142void set_count(int);
143
144void do_something(Context*);
145```
146
147###### Wrong:
148
149```cpp
150void set_count(int count);
151
152void do_something(Context* context);
153```
154
155[](#names-enum-to-bool) Prefer enums to bools on function parameters if callers are likely to be passing constants, since named constants are easier to read at the call site. An exception to this rule is a setter function, where the name of the function already makes clear what the boolean is.
156
157###### Right:
158
159```cpp
160do_something(something, AllowFooBar::Yes);
161paint_text_with_shadows(context, ..., text_stroke_width > 0, is_horizontal());
162set_resizable(false);
163```
164
165###### Wrong:
166
167```cpp
168do_something(something, false);
169set_resizable(NotResizable);
170```
171
172[](#names-enum-members) Enum members should use InterCaps with an initial capital letter.
173
174[](#names-const-to-define) Prefer `const` to `#define`. Prefer inline functions to macros.
175
176[](#names-define-constants) `#defined` constants should use all uppercase names with words separated by underscores.
177
178[](#header-guards) Use `#pragma once` instead of `#define` and `#ifdef` for header guards.
179
180###### Right:
181
182```cpp
183// MyClass.h
184#pragma once
185```
186
187###### Wrong:
188
189```cpp
190// MyClass.h
191#ifndef MyClass_h
192#define MyClass_h
193```
194
195### Other Punctuation
196
197[](#punctuation-member-init) Constructors for C++ classes should initialize their members using C++ initializer syntax. Each member (and superclass) should be indented on a separate line, with the colon or comma preceding the member on that line. Prefer initialization at member definition whenever possible.
198
199###### Right:
200
201```cpp
202class MyClass {
203 ...
204 Document* m_document { nullptr };
205 int m_my_member { 0 };
206};
207
208MyClass::MyClass(Document* document)
209 : MySuperClass()
210 , m_document(document)
211{
212}
213
214MyOtherClass::MyOtherClass()
215 : MySuperClass()
216{
217}
218```
219
220###### Wrong:
221
222```cpp
223MyClass::MyClass(Document* document) : MySuperClass()
224{
225 m_myMember = 0;
226 m_document = document;
227}
228
229MyClass::MyClass(Document* document) : MySuperClass()
230 : m_my_member(0) // This should be in the header.
231{
232 m_document = document;
233}
234
235MyOtherClass::MyOtherClass() : MySuperClass() {}
236```
237
238[](#punctuation-vector-index) Prefer index or range-for over iterators in Vector iterations for terse, easier-to-read code.
239
240###### Right:
241
242```cpp
243for (auto& child : children)
244 child->do_child_thing();
245```
246
247
248#### OK:
249
250```cpp
251for (int i = 0; i < children.size(); ++i)
252 children[i]->do_child_thing();
253```
254
255###### Wrong:
256
257```cpp
258for (auto it = children.begin(); it != children.end(); ++it)
259 (*it)->do_child_thing();
260```
261
262### Pointers and References
263
264[](#pointers-cpp) **Pointer and reference types in C++ code**
265Both pointer types and reference types should be written with no space between the type name and the `*` or `&`.
266
267[](#pointers-out-argument) An out argument of a function should be passed by reference except rare cases where it is optional in which case it should be passed by pointer.
268
269###### Right:
270
271```cpp
272void MyClass::get_some_value(OutArgumentType& out_argument) const
273{
274 out_argument = m_value;
275}
276
277void MyClass::do_something(OutArgumentType* out_argument) const
278{
279 do_the_thing();
280 if (out_argument)
281 *out_argument = m_value;
282}
283```
284
285###### Wrong:
286
287```cpp
288void MyClass::get_some_value(OutArgumentType* outArgument) const
289{
290 *out_argument = m_value;
291}
292```
293
294### "using" Statements
295
296[](#using-ak) In header files in the AK sub-library, however, it is acceptable to use "using" declarations at the end of the file to import one or more names in the AK namespace into the global scope.
297
298###### Right:
299
300```cpp
301// AK/Vector.h
302
303namespace AK {
304
305} // namespace AK
306
307using AK::Vector;
308```
309
310###### Wrong:
311
312```cpp
313// AK/Vector.h
314
315namespace AK {
316
317} // namespace AK
318
319using namespace AK;
320```
321
322###### Wrong:
323
324```cpp
325// runtime/Object.h
326
327namespace AK {
328
329} // namespace AK
330
331using AK::SomethingOrOther;
332```
333
334[](#using-in-cpp) In C++ implementation files, do not use "using" declarations of any kind to import names in the standard template library. Directly qualify the names at the point they're used instead.
335
336###### Right:
337
338```cpp
339// File.cpp
340
341std::swap(a, b);
342c = std::numeric_limits<int>::max()
343```
344
345###### Wrong:
346
347```cpp
348// File.cpp
349
350using std::swap;
351swap(a, b);
352```
353
354###### Wrong:
355
356```cpp
357// File.cpp
358
359using namespace std;
360swap(a, b);
361```
362
363### Types
364
365[](#types-unsigned) Omit "int" when using "unsigned" modifier. Do not use "signed" modifier. Use "int" by itself instead.
366
367###### Right:
368
369```cpp
370unsigned a;
371int b;
372```
373
374###### Wrong:
375
376```cpp
377unsigned int a; // Doesn't omit "int".
378signed b; // Uses "signed" instead of "int".
379signed int c; // Doesn't omit "signed".
380```
381
382### Classes
383
384[](#classes-explicit) Use a constructor to do an implicit conversion when the argument is reasonably thought of as a type conversion and the type conversion is fast. Otherwise, use the explicit keyword or a function returning the type. This only applies to single argument constructors.
385
386###### Right:
387
388```cpp
389class LargeInt {
390public:
391 LargeInt(int);
392...
393
394class Vector {
395public:
396 explicit Vector(int size); // Not a type conversion.
397 Vector create(Array); // Costly conversion.
398...
399
400```
401
402###### Wrong:
403
404```cpp
405class Task {
406public:
407 Task(ExecutionContext&); // Not a type conversion.
408 explicit Task(); // No arguments.
409 explicit Task(ExecutionContext&, Other); // More than one argument.
410...
411```
412
413### Singleton pattern
414
415[](#singleton-static-member) Use a static member function named "the()" to access the instance of the singleton.
416
417###### Right:
418
419```cpp
420class UniqueObject {
421public:
422 static UniqueObject& the();
423...
424```
425
426###### Wrong:
427
428```cpp
429class UniqueObject {
430public:
431 static UniqueObject& shared();
432...
433```
434
435###### Wrong:
436
437```cpp
438class UniqueObject {
439...
440};
441
442UniqueObject& my_unique_object(); // Free function.
443```
444
445### Comments
446
447[](#comments-sentences) Make comments look like sentences by starting with a capital letter and ending with a period (punctation). One exception may be end of line comments like this `if (x == y) // false for NaN`.
448
449[](#comments-fixme) Use FIXME: (without attribution) to denote items that need to be addressed in the future.
450
451###### Right:
452
453```cpp
454draw_jpg(); // FIXME: Make this code handle jpg in addition to the png support.
455```
456
457###### Wrong:
458
459```cpp
460draw_jpg(); // FIXME(joe): Make this code handle jpg in addition to the png support.
461```
462
463```cpp
464draw_jpg(); // TODO: Make this code handle jpg in addition to the png support.
465```
466
467### Overriding Virtual Methods
468
469[](#override-methods) The declaration of a virtual method inside a class must be declared with the `virtual` keyword. All subclasses of that class must either specify the `override` keyword when overriding the virtual method or the `final` keyword when overriding the virtual method and requiring that no further subclasses can override it.
470
471###### Right:
472
473```cpp
474class Person {
475public:
476 virtual String description() { ... };
477}
478
479class Student : public Person {
480public:
481 virtual String description() override { ... }; // This is correct because it only contains the "override" keyword to indicate that the method is overridden.
482}
483
484```
485
486```cpp
487class Person {
488public:
489 virtual String description() { ... };
490}
491
492class Student : public Person {
493public:
494 virtual String description() final { ... }; // This is correct because it only contains the "final" keyword to indicate that the method is overridden and that no subclasses of "Student" can override "description".
495}
496
497```
498
499###### Wrong:
500
501```cpp
502class Person {
503public:
504 virtual String description() { ... };
505}
506
507class Student : public Person {
508public:
509 String description() override { ... }; // This is incorrect because it uses only the "override" keywords to indicate that the method is virtual. Instead, it should use both the "virtual" and "override" keywords.
510}
511```
512
513```cpp
514class Person {
515public:
516 virtual String description() { ... };
517}
518
519class Student : public Person {
520public:
521 String description() final { ... }; // This is incorrect because it uses only the "final" keywords to indicate that the method is virtual and final. Instead, it should use both the "virtual" and "final" keywords.
522}
523```
524
525```cpp
526class Person {
527public:
528 virtual String description() { ... };
529}
530
531class Student : public Person {
532public:
533 virtual String description() { ... }; // This is incorrect because it uses the "virtual" keyword to indicate that the method is overridden.
534}
535```
536