We use clang-format v12 to conform our code style according to the rules outlined below.
@note These rules are applied to any C/C++ source code that is not Arduino example code. For the code style used in the Arduino examples, please refer to the Arduino example formatting style guide.
- Indentation should always be 4 spaces (don't use tab characters)
- Line endings can be whatever your system defaults to. We have configured git to convert line endings into Unix style LF. This means that when you develop (and push commits) from a Windows machine, the CRLF line endings are automatically converted to LF line endings.
Any data structure with explicit access modifiers (public
, private
, or protected
)
should carry the same indentation as the data structure's declaration.
class MyClass {
public:
}
Align parameters on the open bracket.
someLongFunction(argument1,
argument2);
Align macro definitions on consecutive lines.
#define SHORT_NAME 42
#define LONGER_NAME 0x007f
#define EVEN_LONGER_NAME (2)
#define foo(x) (x * x)
/* some comment */
#define bar(y, z) (y + z)
Align escaped newlines as far left as possible.
#define A \
int aaaa; \
int b; \
int dddddddddd;
For consecutive lines in a "paragraph" that have trailing comments, the comments should be aligned vertically. The aligning column is 1 space after the longest line in the "paragraph".
See also SpacesBeforeTrailingComments
int a; // My comment a
int b = 2; // comment b
If a function call or braced initializer list doesn't fit on a line, allow putting all arguments onto the next line.
callFunction(
a, b, c, d);
If a constructor definition with a member initializer list doesn't fit on a single line, allow putting all member initializers onto the next line.
MyClass::MyClass() :
member0(0), member1(2) {}
If the function declaration doesn't fit on a line, allow putting all parameters of a function declaration onto the next line.
void myFunction(
int a, int b, int c, int d, int e);
Allow short enums on a single line.
enum { A, B } myEnum;
Always merge short blocks into a single line.
while (true) {}
while (true) { continue; }
Short case labels should be on single line.
switch (a) {
case 1: x = 1; break;
case 2: return;
}
Merge all functions fitting on a single line.
class Foo {
void f() { foo(); }
};
void f() { bar(); }
Merge all lambdas fitting on a single line.
auto lambda = [](int a) {}
auto lambda2 = [](int a) { return a; };
Put short if
s on the same line only if the else
is not a compound statement.
if (a) return;
else
return;
Short loops can be put on a single line.
while (true) continue;
A function's return type should not get its own line.
class A {
int f() { return 0; };
};
int f();
int f() { return 1; }
This flag is mean to make cases where there are multiple multiline strings in a file look more consistent. The subsequent indent should align with the beginning of the string.
aaaa = "bbbb"
"cccc";
Always break after template declaration.
template <typename T>
T foo() {
}
template <typename T>
T foo(int aaaaaaaaaaaaaaaaaaaaa,
int bbbbbbbbbbbbbbbbbbbbb) {
}
A function call's multitude of arguments can span multiple lines without needing 1 line per argument.
void f() {
f(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
}
A function declaration's multitude of arguments can span multiple lines without needing 1 line per argument.
void f(int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
Add one space on each side of the :
unsigned bf : 2;
Control of individual brace wrapping cases.
switch (foo) {
case 1: {
bar();
break;
}
default: {
plop();
}
}
class foo {};
Only wrap braces after a multi-line control statement (if
/for
/while
/switch
/...).
if (foo && bar &&
baz)
{
qux();
}
while (foo || bar) {
}
enum X : int
{
B
};
void foo()
{
bar();
bar2();
}
namespace {
int foo();
int bar();
}
struct foo
{
int x;
};
union foo
{
int x;
}
extern "C" {
int foo();
}
try {
foo();
}
catch () {
}
if (foo()) {
}
else {
}
connect([]() {
foo();
bar();
});
do {
foo();
} while (1);
class Foo()
{
}
Break before binary operators whose operands span multiple lines.
VeryVeryVeryVeryVeryLongType veryVeryVeryVeryVeryLongVariable
= someVeryVeryVeryVeryLongFunction();
bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
== aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
&& aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> ccccccccccccccccccccccccccccccccccccccccc;
Concept should be placed on a new line.
template<typename T>
concept ...
Break inheritance list before the colon and after the commas.
class Foo
: Base1,
Base2
{};
Ternary operators should be placed after line breaks (if the operands span multiple lines).
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription
? firstValue
: SecondValueVeryVeryVeryVeryLong;
Break constructor initializers before the colon and after the commas.
Constructor()
: initializer1(),
initializer2()
Breaking string literals into multiple lines is allowed.
const char* x = "veryVeryVeryVeryVeryVe"
"ryVeryVeryVeryVeryVery"
"VeryLongString";
There is no line length limit.
Each namespace is declared on a new line.
namespace Foo {
namespace Bar {
}
}
format braced lists as best suited for C++11 braced lists.
Important differences:
- No spaces inside the braced list.
- No line break before the closing brace.
- Indentation with the continuation indent, not with the block indent.
vector<int> x{1, 2, 3, 4};
vector<T> x{{}, {}, {}, {}};
f(MyMap[{composite, key}]);
new int[3]{1, 2, 3};
Always add empty line before access modifiers unless access modifier is at the start of struct or class definition.
struct foo {
private:
int i;
protected:
int j;
/* comment */
public:
foo() {}
private:
protected:
};
Add namespace end comments.
namespace a {
foo();
} // namespace a
Switch statement body is always indented one level more than case labels (except the first block following the case label, which itself indents the code)
switch (fool) {
case 1:
bar();
break;
default:
plop();
}
Goto labels are flushed left.
int f() {
if (foo()) {
label1:
bar();
}
label2:
return 1;
}
Indents directives before the hash.
#if FOO
#if BAR
#include <foo>
#endif
#endif
Do not indent extern blocks.
extern "C" {
void foo();
}
Do not indent the requires clause in a template.
template <typename It>
requires Iterator<It>
void sort(It begin, It end) {
//....
}
Indentation is 4 spaces.
Do not Indent if a function definition or declaration is wrapped after the type.
LoooooooooooooooooooooooooooooooooooooooongReturnType
LoooooooooooooooooooooooooooooooongFunctionDeclaration();
The (optional) empty line at the start of blocks is kept.
if (foo) {
bar();
}
Consecutive empty lines are reduced to 1.
Indent only in inner namespaces (nested in other namespaces).
namespace out {
int i;
namespace in {
int i;
}
}
Align pointer to the left.
int* a;
This is only applicable if we decide to impose a line length (which we are not)
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
// information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information */
Do not insert a space after C style casts.
(int)i;
Do not insert a space after the logical not operator (!
).
!someExpression();
Do not insert a space after the template
keyword.
template<int> void foo();
A spaces will be inserted before assignment operators.
int a = 5;
a += 42;
Spaces will be removed before case colon.
switch (x) {
case 1: break;
}
A space will be inserted before a C++11 braced list used to initialize an object (after the preceding identifier or type).
Foo foo { bar };
Foo {};
vector<int> { 1, 2, 3 };
new int[3] { 1, 2, 3 };
A space will be inserted before a constructor initializer colon.
Foo::Foo() : a(a) {}
A space will be inserted before a inheritance colon.
class Foo : Bar {}
Put a space before opening parentheses only after control statement keywords (for
/if
/while
...).
void f() {
if (true) {
f();
}
}
A space will be inserted before a range-based for loop colon.
for (auto v : values) {}
Do not use spaces for an empty set of parenthesis.
void f() {
int x[] = {foo(), bar()};
}
Use a space before trailing line comments (//
- comments).
This does not affect trailing block comments (/*
- comments) as those commonly have different usage patterns and a number of special cases.
void f() {
if (true) { // foo1
f(); // bar
} // foo
}
Spaces will be removed after <
and before >
in template argument lists.
static_cast<int>(arg);
std::function<void(int)> fct;
Spaces will be removed around if
/for
/switch
/while
conditions.
if (a) { ... }
while (i < 5) { ... }
Spaces are inserted inside container literals.
var arr = [1, 2, 3];
f({a: 1, b: 2, c: 3});
Spaces will be removed from C style casts.
x = (int32)y;
Spaces will be removed after (
and before )
.
t f(Deleted &) & = delete;
Spaces will be removed after [
and before ]
.
int a[5];
Spaces will be removed before [
.
int a[5];
int a[5][5];
Follow the C++11 standard format.
A tab's width is considered equal to 4 spaces.
Only use spaces (not tabs).
This project is primarily for Linux platforms, so we prefer to have LF line endings. We don't use Windows-style CRLF line endings.
Allows empty lines after a data structure's access modifiers.
class MyClass {
public:
MyClass();
private:
_some_private_function();
};
Do not indent data structures' access modifiers. They should be the same indentation as the structure's definition.
Inline comments (beginning with //
) do not need any mandatory spaces before the comment content. Additionally, there is no maximum space mandated.
The number of lines that qualifies a short namespace definition is 0. This is so a closing brace (}
) for a namespace is always postfixed with a comment that indicates the end of a namespace definition.
namespace a {
int foo;
} // namespace a