]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/coding-style.md
import quincy beta 17.1.0
[ceph.git] / ceph / src / seastar / coding-style.md
CommitLineData
11fdf7f2
TL
1# Seastar Coding Style
2
3## Files
4
5Header files have the `.hh` extension, source files use the `.cc` extension. All files must have a license and copyright blurb. Use `#pragma once` instead of an include guard.
6
7Header files which contain a public part of the interface of Seastar go in the `include` directory. Internal header and source files which are private to the implementation go in the `src` directory.
8
9## Whitespace
10
11Use spaces only; NEVER tabs. Rationale: tabs render differently on each system.
12
13An _indent_ is four spaces. A double indent is eight spaces, a half-indent is two spaces.
14
15## Naming
16
20effc67 17We follow the C++ and Boost naming conventions: class names, variables, functions, and concepts are `words_separated_by_whitespace`.
11fdf7f2
TL
18
19Private data members are prefixed by an underscore:
20
21```c++
22class my_class {
23 int _a_member;
24public:
25 void foo() {
26 _a_member = 3;
27 }
28};
29```
30
31Think of the leading underscore as a shorthand for `this->`.
32
20effc67
TL
33Template parameters use `CamelCase`
34
35Note: because the Concept Technical Specification used CamelCase for concepts,
36some Seastar concepts alse use CamelCase. These will be gradually deprecated
37and replaced with snake_case names. New concepts should use snake_case.
11fdf7f2
TL
38
39## Including header files
40
41In any file, to include a public header file (one in the `include` directory), use an absolute path with `<>` like this:
42
43```c++
44#include <seastar/core/future.hh>
45```
46
47In any private file, to include a private header file (one in the `src` directory), use an absolute path with `""` like this:
48
49```c++
50#include "core/future_impl.hh"
51```
52
53## Braced blocks
54
55All nested scopes are braced, even when the language allows omitting the braces (such as an if-statement), this makes patches simpler and is more consistent. The opening brace is merged with the line that opens the scope (class definition, function definition, if statement, etc.) and the body is indented.
56
57```c++
58void a_function() {
59 if (some condition) {
60 stmt;
61 } else {
62 stmt;
63 }
64}
65```
66
67An exception is namespaces -- the body is _not_ indented, to prevent files that are almost 100% whitespace left margin.
68
69When making a change, if you need to insert an indentation level, you can temporarily break the rules by insering a half-indent, so that the patch is easily reviewable:
70
71```c++
72void a_function() {
73 while (something) { // new line - half indent
74 if (some condition) {
75 stmt;
76 } else {
77 stmt;
78 }
79 } // new line
80}
81```
82
83A follow-up patch can restore the indents without any functional changes.
84
85## Function parameters
86
87Avoid output parameters; use return values instead. In/out parameters are tricky, but in some cases they are relatively standard, such as serialization/deserialization.
88
89If a function accepts a lambda or an `std::function`, make it the last argument, so that it can be easily provided inline:
90
91```c++
92template <typename Func>
93void function_accepting_a_lambda(int a, int b, Func func);
94
95int f() {
96 return function_accepting_a_lambda(2, 3, [] (int x, int y) {
97 return x + y;
98 });
99}
100```
101
102## Complex return types
103
104If a function returns a complicated return type, put its return type on a separate line, otherwise it becomes hard to see where the return type ends and where the function name begins:
105
106```c++
107template <typename T1, T2>
108template <typename T3, T4>
109std::vector<typename a_struct<T1, T2>::some_nested_class<T3, T4>> // I'm the return type
110a_struct<T1, T2>::a_function(T3 a, T4 b) { // And I'm the function name
111 // ...
112}
113```
114
115## Whitespace around operators
116
117Whitespace around operators should match their precedence: high precedence = no spaces, low precedency = add spaces:
118
119```c++
120 return *a + *b; // good
121 return * a+* b; // bad
122```
123
124`if`, `while`, `return` (and `template`) are not function calls, so they get a space after the keyword.
125
126## Long lines
127
128If a line becomes excessively long (>120 characters?), or is just complicated, break it into two or more lines. The second (and succeeding lines) are _continuation lines_, and have a double indent:
129
130```c++
131 if ((some_condition && some_other_condition)
132 || (more complicated stuff here...) // continuation line, double indent
133 || (even more complicated stuff)) { // another continuation line
134 do_something(); // back to single indent
135 }
136```
137
138Of course, long lines or complex conditions may indicate that refactoring is in order.
139
9f95a23c
TL
140## Generic lambdas and types
141
142Generic lambdas (`[] (auto param)`) are discouraged where the type is known. Generic
143lambdas reduce the compiler's and other tools' ability to reason about the code.
144In case the actual type of `param` doesn't match the programmers expectations,
145the compiler will only detect an error in the lambda body, or perhaps
146even lower down the stack if more generic functions are called. In the case of an
147IDE, most of its functionality is disabled in a generic lambda, since it can't
148assume anything about that parameter.
149
150Of course, when there is a need to support multiple types, genericity is the correct
151tool. Even then, type parameters should be constrained with concepts, in order to
152catch type mismatches early rather than deep in the instantiation chain.
153
154