This document describes the styles and patterns used this project. All fresh code should conform to these rules, so it is as easy to maintain as existing code.
-
Use spaces, not tabs. Tabs should only appear in files that require them for semantic meaning, like Makefiles.
-
The indent size is 4 spaces.
-
The contents of an outermost namespace block (and any nested namespaces with the same scope) should not be indented. The contents of other nested namespaces should be indented.
Right:
namespace MyNamespace {
class MyClass {
MyClass();
...
};
namespace MyNestedNamespace {
class MyOtherClass {
MyOtherClass();
...
};
}
}
Wrong:
namespace MyNamespace {
class MyClass {
MyClass();
...
};
namespace MyNestedNamespace {
class MyOtherClass {
MyOtherClass();
...
};
}
}
- A case label should line up with its switch statement. The case statement is indented.
Right:
switch (condition) {
case foo:
case bar:
i++;
break;
default:
i--;
}
Wrong:
switch (condition) {
case foo:
case bar:
i++;
break;
default:
i--;
}
-
Statements longer than 100 columns should be broken into sensible chunks
-
Each statement should get its own line.
Right:
x++;
y++;
if (condition) {
do();
}
Wrong:
x++; y++;
if (condition) { do(); }
- Function definitions: place each brace on its own line.
Right:
int Function()
{
...
}
Wrong:
int Function() {
...
}
- Other braces: place the open brace on the line preceding the code block; place the close brace on its own line.
Right:
class MyClass {
...
};
namespace MyNamespace {
...
}
for (int i = 0; i < 10; ++i) {
...
}
Wrong:
class MyClass
{
...
};
namespace MyNamespace
{
...
}
for (int i = 0; i < 10; ++i)
{
...
}
- Always brace controlled statements, even a single-line consequent of
if else
. This is redundant, typically, but it avoids dangling else bugs, so it's safer at scale than fine-tuning.
Right:
if (condition) {
do();
}
Wrong:
if (condition) do();
-
No blank spaces at the end of a line
-
Do not place spaces around unary operators.
Right:
i++;
Wrong:
i ++;
- Use one space around (on each side of) most binary and ternary operators, such as any of these:
= + - < > * / % | & ^ <= >= == != ? :
but no space after unary operators:
& * + - ~ ! sizeof typeof alignof defined
and no space around the .
and ->
structure member operators.
Right:
y = m * x + b;
f(a, b);
c = a | b;
return condition ? 1 : 0;
Wrong:
y=m*x+b;
f(a,b);
c = a|b;
return condition ? 1:0;
- Do not place spaces before comma and semicolon.
Right:
for (int i = 0; i < 10; ++i)
doSomething();
f(a, b);
Wrong:
for (int i = 0 ; i < 10 ; ++i)
doSomething();
f(a , b) ;
- Place spaces between control statements and their parentheses.
Right:
if (condition)
doIt();
Wrong:
if(condition)
doIt();
- Do not place spaces between a function and its parentheses, or between a parenthesis and its content.
Right:
f(a, b);
Wrong:
f (a, b);
f( a, b );
- When initializing an object, place a space before the leading brace as well as between the braces and their content.
Right:
Foo foo { bar };
Wrong:
Foo foo{ bar };
Foo foo {bar};
- 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 start with"g_"
Right:
int g_variable;
class String {
public:
...
private:
short m_length;
};
Wrong:
int variable;
class String {
public:
...
private:
short length;
};
- Precede boolean values with words like
"is"
.
Right:
bool isValid;
Wrong:
bool Valid;
- Precede setters with the word
"set"
. Precede getters with the word"get"
.
Right:
void setCount(size_t); // sets m_count
size_t getCount(); // returns m_count
Wrong:
void Count(size_t); // sets m_count
size_t Count(); // returns m_count
- Put * and & by the variable name rather than the type.
Right:
bool fooBar(bool Baz, char *str, std::vector<int> &Result);
Wrong:
bool fooBar(bool Baz, char* str, std::vector<int>& Result);
-
Include headers in the following order:
config.h
, Related header, C system headers, C++ standard library headers, other libraries' headers, your project's headers..- Pros:
- Forward declarations can save compile time, as #includes force the compiler to open more files and process more input.
- Forward declarations can save on unnecessary recompilation. #includes can force your code to be recompiled more often, due to unrelated changes in the header.
- Cons:
- Forward declarations can hide a dependency, allowing user code to skip necessary recompilation when headers change.
- A forward declaration as opposed to an #include statement makes it difficult for automatic tooling to discover the module defining the symbol.
- A forward declaration may be broken by subsequent changes to the library. Forward declarations of functions and templates can prevent the header owners from making otherwise-compatible changes to their APIs, such as widening a parameter type, adding a template parameter with a default value, or migrating to a new namespace.
- Forward declaring multiple symbols from a header can be more verbose than simply #includeing the header.
Right:
#include "config.h"
#include "foo/server/fooserver.h"
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/commandlineflags.h"
#include "foo/server/bar.h"
- Comments are important for readability and maintainability. When writing comments, write them as English prose, using proper capitalization, punctuation, etc.
- Generally, you want your comments to tell WHAT your code does, not HOW
- In general, prefer C++-style comments for one line.
- The preferred style for long (multi-line) comments is:
/* The preferred comment style for (multi-line) comments
* looks like this.
*/
Fields and methods must be grouped together respectively and regardless of their visibility. All the fields must be either at the top or bottom of a class definition. It is discouraged to mix methods and fields.
Rationale: fields layout matters in context of padding and cache miss optimizations. Mixing fields and methods complicates visual perception and estimation of the resulting ABI.
Right:
class foo {
public:
foo();
void method1();
protected:
void method2();
private:
void method3();
public:
int field1;
protected:
int field2;
private:
int field3;
};
Visibility mode doesn't have to be repeated if it is not changed for the block with fields (or methods).
Right:
class bar {
public:
bar();
method1();
private:
method2();
int field1;
int field2;
};
auto keyword can simplify code, but it can also be harmful. Follow the recommendations:
- It is encouraged to use auto keyword for an iterator declaration and inside templates if it simplifies the code.
- Keyword auto may be used if the initializer is a class name and only if it doesn't complicates code readability and parsing.
- It is discouraged to use auto keyword in other situations.
Rationale: there are multiple concerns for auto keyword:
- Can hide type of the variable and it will require to put more effort to derive the type and understand impact of the code.
- Hidden type complicates estimation of bit operations and integer promotion.
- Complicates parsing of the code, specific places can be unnoticed during conversion or routine changes.
- Can hide errors since specific code can be compilable after a type change, but become incorrect.
- Can hide performance critical knowledge (e.g. whether assignment uses copy or reference).