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 15 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
14A 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
34Use 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
52Data 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
77Precede 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
93Precede 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
107Use 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
121When there are two getters for a variable, and one of them automatically makes sure the requested object is instantiated, prefix that getter function 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
137Leave 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
155Prefer 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
172Enum members should use InterCaps with an initial capital letter.
173
174Prefer `const` to `#define`. Prefer inline functions to macros.
175
176`#defined` constants should use all uppercase names with words separated by underscores.
177
178Use `#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
197Constructors 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
238Prefer 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
264Both pointer types and reference types should be written with no space between the type name and the `*` or `&`.
265
266An 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.
267
268###### Right:
269
270```cpp
271void MyClass::get_some_value(OutArgumentType& out_argument) const
272{
273 out_argument = m_value;
274}
275
276void MyClass::do_something(OutArgumentType* out_argument) const
277{
278 do_the_thing();
279 if (out_argument)
280 *out_argument = m_value;
281}
282```
283
284###### Wrong:
285
286```cpp
287void MyClass::get_some_value(OutArgumentType* outArgument) const
288{
289 *out_argument = m_value;
290}
291```
292
293### "using" Statements
294
295In 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.
296
297###### Right:
298
299```cpp
300// AK/Vector.h
301
302namespace AK {
303
304} // namespace AK
305
306using AK::Vector;
307```
308
309###### Wrong:
310
311```cpp
312// AK/Vector.h
313
314namespace AK {
315
316} // namespace AK
317
318using namespace AK;
319```
320
321###### Wrong:
322
323```cpp
324// runtime/Object.h
325
326namespace AK {
327
328} // namespace AK
329
330using AK::SomethingOrOther;
331```
332
333In 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.
334
335###### Right:
336
337```cpp
338// File.cpp
339
340std::swap(a, b);
341c = std::numeric_limits<int>::max()
342```
343
344###### Wrong:
345
346```cpp
347// File.cpp
348
349using std::swap;
350swap(a, b);
351```
352
353###### Wrong:
354
355```cpp
356// File.cpp
357
358using namespace std;
359swap(a, b);
360```
361
362### Types
363
364Omit "int" when using "unsigned" modifier. Do not use "signed" modifier. Use "int" by itself instead.
365
366###### Right:
367
368```cpp
369unsigned a;
370int b;
371```
372
373###### Wrong:
374
375```cpp
376unsigned int a; // Doesn't omit "int".
377signed b; // Uses "signed" instead of "int".
378signed int c; // Doesn't omit "signed".
379```
380
381### Classes
382
383For types with methods, prefer `class` over `struct`.
384
385* For classes, make public getters and setters, keep members private with `m_` prefix.
386* For structs, let everything be public and skip the `m_` prefix.
387
388###### Right:
389
390```cpp
391struct Thingy {
392 String name;
393 int frob_count { 0 };
394};
395
396class Doohickey {
397public:
398 String const& name() const { return m_name; }
399 int frob_count() const { return m_frob_count; }
400
401 void jam();
402
403private:
404 String m_name;
405 int m_frob_count { 0 };
406}
407```
408
409###### Wrong:
410
411```cpp
412struct Thingy {
413public:
414 String m_name;
415 int frob_count() const { return m_frob_count; }
416
417private:
418 int m_frob_count { 0 };
419}
420
421class Doohickey {
422public:
423 String const& name() const { return this->name; }
424
425 void jam();
426
427 String name;
428 int frob_count { 0 };
429};
430```
431
432Use 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.
433
434###### Right:
435
436```cpp
437class LargeInt {
438public:
439 LargeInt(int);
440...
441
442class Vector {
443public:
444 explicit Vector(int size); // Not a type conversion.
445 Vector create(Array); // Costly conversion.
446...
447
448```
449
450###### Wrong:
451
452```cpp
453class Task {
454public:
455 Task(ExecutionContext&); // Not a type conversion.
456 explicit Task(); // No arguments.
457 explicit Task(ExecutionContext&, Other); // More than one argument.
458...
459```
460
461### Singleton pattern
462
463Use a static member function named "the()" to access the instance of the singleton.
464
465###### Right:
466
467```cpp
468class UniqueObject {
469public:
470 static UniqueObject& the();
471...
472```
473
474###### Wrong:
475
476```cpp
477class UniqueObject {
478public:
479 static UniqueObject& shared();
480...
481```
482
483###### Wrong:
484
485```cpp
486class UniqueObject {
487...
488};
489
490UniqueObject& my_unique_object(); // Free function.
491```
492
493### Comments
494
495Make comments look like sentences by starting with a capital letter and ending with a period (punctuation). One exception may be end of line comments like this `if (x == y) // false for NaN`.
496
497Use FIXME: (without attribution) to denote items that need to be addressed in the future.
498
499###### Right:
500
501```cpp
502draw_jpg(); // FIXME: Make this code handle jpg in addition to the png support.
503```
504
505###### Wrong:
506
507```cpp
508draw_jpg(); // FIXME(joe): Make this code handle jpg in addition to the png support.
509```
510
511```cpp
512draw_jpg(); // TODO: Make this code handle jpg in addition to the png support.
513```
514
515Explain *why* the code does something. The code itself should already say what is happening.
516
517###### Right:
518
519```cpp
520i++; // Go to the next page.
521```
522
523```cpp
524// Let users toggle the advice functionality by clicking on catdog.
525catdog_widget.on_click = [&] {
526 if (advice_timer->is_active())
527 advice_timer->stop();
528 else
529 advice_timer->start();
530};
531```
532
533###### Even better:
534
535```cpp
536page_index++;
537```
538
539###### Wrong:
540
541```cpp
542i++; // Increment i.
543```
544
545```cpp
546// If the user clicks, toggle the timer state.
547catdog_widget.on_click = [&] {
548 if (advice_timer->is_active())
549 advice_timer->stop();
550 else
551 advice_timer->start();
552};
553```
554
555### Overriding Virtual Methods
556
557The declaration of a virtual method inside a class must be declared with the `virtual` keyword. All subclasses of that class must also specify either 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.
558
559###### Right:
560
561```cpp
562class Person {
563public:
564 virtual String description() { ... };
565}
566
567class Student : public Person {
568public:
569 virtual String description() override { ... }; // This is correct because it contains both the "virtual" and "override" keywords to indicate that the method is overridden.
570}
571
572```
573
574```cpp
575class Person {
576public:
577 virtual String description() { ... };
578}
579
580class Student : public Person {
581public:
582 virtual String description() final { ... }; // This is correct because it contains both the "virtual" and "final" keywords to indicate that the method is overridden and that no subclasses of "Student" can override "description".
583}
584
585```
586
587###### Wrong:
588
589```cpp
590class Person {
591public:
592 virtual String description() { ... };
593}
594
595class Student : public Person {
596public:
597 String description() override { ... }; // This is incorrect because it uses only the "override" keyword to indicate that the method is virtual. Instead, it should use both the "virtual" and "override" keywords.
598}
599```
600
601```cpp
602class Person {
603public:
604 virtual String description() { ... };
605}
606
607class Student : public Person {
608public:
609 String description() final { ... }; // This is incorrect because it uses only the "final" keyword to indicate that the method is virtual and final. Instead, it should use both the "virtual" and "final" keywords.
610}
611```
612
613```cpp
614class Person {
615public:
616 virtual String description() { ... };
617}
618
619class Student : public Person {
620public:
621 virtual String description() { ... }; // This is incorrect because it uses only the "virtual" keyword to indicate that the method is overridden.
622}
623```
624
625### Const placement
626
627Use "east const" style where `const` is written on the right side of the type being qualified. See [this article](https://mariusbancila.ro/blog/2018/11/23/join-the-east-const-revolution/) for more information about east const.
628
629###### Right:
630
631```cpp
632Salt const& m_salt;
633```
634
635###### Wrong:
636
637```cpp
638const Salt& m_salt;
639```
640
641### Casts
642
643Before you consider a cast, please see if your problem can be solved another way that avoids the visual clutter.
644
645- Integer constants can be specified to have (some) specific sizes with postfixes like `u, l, ul` etc. The same goes for single-precision floating-point constants with `f`.
646- Working with smaller-size integers in arithmetic expressions is hard because of [implicit promotion](https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules). Generally, it is fine to use `int` and other "large" types in local variables, and possibly cast at the end.
647- If you `const_cast`, _really_ consider whether your APIs need to be adjusted in terms of their constness. Does the member function you're writing actually make sense to be `const`?
648- If you do checked casts between base and derived types, also consider your APIs. For example: Does the function being called actually need to receive the more general type or is it fine with the more specialized type?
649
650If you _do_ need to cast: **Don't use C-style casts**. The C-style cast has [complex behavior](https://en.cppreference.com/w/c/language/cast) that is undesired in many instances. Be aware of what sort of type conversion the code is trying to achieve, and use the appropriate (!) C++ cast operator, like `static_cast`, `reinterpret_cast`, `bit_cast`, `dynamic_cast` etc.
651
652There is a single exception to this rule: marking a function parameter as used with `(void)parameter;`.
653
654###### Right:
655```cpp
656MyParentClass& object = get_object();
657// Verify the type...
658MyChildClass& casted = static_cast<MyChildClass&>(object);
659```
660
661```cpp
662// AK::Atomic::exchange()
663
664alignas(T) u8 buffer[sizeof(T)];
665T* ret = reinterpret_cast<T*>(buffer);
666```
667
668```cpp
669// SeekableStream::tell()
670
671// Seek with 0 and SEEK_CUR does not modify anything despite the const_cast,
672// so it's safe to do this.
673return const_cast<SeekableStream*>(this)->seek(0, SeekMode::FromCurrentPosition);
674```
675
676###### Wrong:
677```cpp
678// These should be static_cast.
679size_t mask_length = (size_t)((u8)-1) + 1;
680```
681
682```cpp
683// This should be reinterpret_cast.
684return (u8 const*)string.characters_without_null_termination();
685```
686
687### Omission of curly braces from statement blocks
688
689Curly braces may only be omitted from `if`/`else`/`for`/`while`/etc. statement blocks if the body is a single line.
690
691Additionally, if any body of a connected if/else statement requires curly braces according to this rule, all of them do.
692
693###### Right:
694```cpp
695if (condition)
696 foo();
697```
698
699```cpp
700if (condition) {
701 foo();
702 bar();
703}
704```
705
706```cpp
707if (condition) {
708 foo();
709} else if (condition) {
710 bar();
711 baz();
712} else {
713 qux();
714}
715```
716
717```cpp
718for (size_t i = i; condition; ++i) {
719 if (other_condition)
720 foo();
721}
722```
723
724##### OK:
725
726```cpp
727if (condition) {
728 foo();
729}
730```
731
732###### Wrong:
733
734```cpp
735if (condition)
736 // There is a comment here.
737 foo();
738```
739
740```cpp
741if (condition)
742 foo();
743else {
744 bar();
745 baz();
746} else
747 qux();
748```
749
750```cpp
751for (size_t i = i; condition; ++i)
752 if (other_condition)
753 foo();
754```