Modern C++
Programming
14. Code Conventions
Part II
Federico Busato
2024-11-05
Table of Contents
1 auto
2 Templates and Type Deduction
3 Control Flow
Redundant Control Flow
if/else
Comparison
switch
for/while
1/78
Table of Contents
4 namespace
using namespace Directive
Anonymous/Unnamed Namespace
Namespace and Class Design
Style
5 Modern C++
Keywords
Features
Class
Library
2/78
Table of Contents
6 Maintainability
Code Comprehension
Functions
Template and Deduction
Library
7 Portability
3/78
Table of Contents
8 Naming
Entities
Variables
Functions
Style Conventions
Enforcing Naming Styles
4/78
Table of Contents
9 Readability and Formatting
Horizontal Spacing
Pointers/References
Vertical Spacing
Braces
Type Decorators
Reduce Code Verbosity
Other Issues
5/78
Table of Contents
10 Code Documentation and Comments
Function Documentation
Comment Syntax
File Documentation
6/78
auto
auto
Use auto to avoid type names that are noisy, obvious, or unimportant
auto array = new int[10];
auto var = static cast<int>(var);
........
LLVM,
..........
Google
lambdas, iterators, template expressions
unreal (only)
Do not excessively use auto for variable types. Use auto only when the
left type is easy to deduce looking at the right expression
..........
Google
Don’t use auto when the type would be deduced to be a pointer type
auto* v = new int;
.............
Chromium
Use auto for return type deduction only with small/simple functions and lambda
expressions
..........
Google
7/78
Templates and Type
Deduction
Templates and Type Deduction
Avoid complicated template programming
..........
Google
Prefer automatic template deduction f(0) instead of f<int>(0)
Use class template argument deduction (CTAD) only with templates that provide
at least one explicit deduction guide
..........
Google
Use trailing return types only where using the ordinary syntax is impractical or
much less readable
..........
Google,
..........
Webkit
int foo(int x) instead of auto foo(int x) -> int
8/78
Templates and Type Deduction
Declare template specializations in the same file as the primary template they
specialize
.....
Hic
template<typename T>
f(); // primary template
template<>
f<int>();
Do not place spaces between the identifier template and its angle brackets
..........
Webkit
template<typename U> struct Bar { };
9/78
Control Flow
Control Flow
Limit control flow complexity (cyclomatic/cognitive complexity)
.....
Hic,
......
µOS,
................
Clang-Tidy
Avoid
goto
......
µOS,
............
CoreCpp
10/78
Redundant Control Flow 1/3
Avoid redundant control flow (see next slides)
................
Clang-Tidy,
............
CoreCpp
- Do not use else after a return / break
........
LLVM,
..........
Webkit,
................
Clang-Tidy
- Avoid comparing boolean condition to true/false
...........
Mozilla
- Avoid return true/return false pattern
- Merge multiple conditional statements
11/78
Redundant Control Flow 2/3
if (condition) { // BAD
< body1 >
return; // <--
}
else // <-- redundant
< body2 >
if (condition) { // GOOD
< body1 >
return;
}
< body2 >
if (condition == true) // BAD
if (condition) // GOOD
12/78
Redundant Control Flow 3/3
if (condition) // BAD
return true;
else
return false;
return condition; // GOOD
if (condition1) {
if (condition2) {
if (condition3) { // BAD
if (condition1 && condition2 && condition3) { // GOOD
bool condition4 = condition1 && condition2 && condition3;
if (condition4) { // GOOD
13/78
Control Flow - if/else
The if and else keywords belong on separate lines
if (c1) <statement1>; else <statement2>; // BAD
..........
Google,
..........
Webkit
Don’t use the ternary operator ( ?: ) as a sub-expression
(i != 0) ? ((j != 0) ? 1 : 0) : 0;
.....
Hic
14/78
Control Flow - Comparison
Tests for null/non-null , and zero/non-zero should all be done with
equality comparisons
.....
Hic
(opposite)
...........
Mozilla,
..........
Webkit,
............
CoreCpp
if (!ptr)
return;
if (!count)
return;
if (ptr == nullptr)
return;
if (count == 0)
return;
Prefer (ptr == nullptr) and x > 0 over (nullptr == ptr) and
0 < x
.............
Chromium
15/78
Control Flow - switch
Prefer switch to multiple if -statement
............
CoreCpp
Don’t use default labels in fully covered switch over enumerations
.........
LLVM,
............
CoreCpp
In all other cases, switch statements should always have a default case
..........
Google,
..........
Unreal,
.....
Hic,
................
Clang-Tidy
16/78
Control Flow - switch - Style
case blocks in switch statements are indented twice
..........
Google
switch (var) {
case 0: {
Foo();
break;
}
}
A case label should line up with its switch statement. The case statement is
indented
..........
Webkit
switch (var) {
case 0:
Foo();
break;
}
17/78
Control Flow - for/while 1/3
Use range-based for loops whenever possible
.........
LLVM,
..........
Unreal,
...............
Clang-Tidy,
............
CoreCpp
1
,
............
CoreCpp
2
,
............
CoreCpp
3
Prefer a for -statement to a while -statement when there is an obvious loop
variable
............
CoreCpp
Prefer a while -statement to a for -statement when there is no obvious loop
variable
............
CoreCpp
Avoid do-while loop
............
CoreCpp
18/78
Control Flow - for/while 2/3
Use early exits ( continue , break , return ) to simplify the code
.........
LLVM,
............
CoreCpp
for (<condition1>) { // BAD
if (<condition2>)
...
}
for (<condition1>) { // GOOD
if (!<condition2>)
continue;
...
}
19/78
Control Flow - for/while 3/3
Turn predicate loops into predicate functions
.........
LLVM,
............
CoreCpp
bool var = ...;
for (<loop_condition1>) { // should be an external
if (<condition2>) { // function
var = ...
break;
}
20/78
namespace
Namespace
Always place code in a namespace to avoid global namespace pollution
..........
Google
Do not use namespace aliases namespace nsA = other namespace at
namespace/global scope in header files except in explicitly marked
internal-only namespaces
...........
Google,
...........
Mozilla
Do not declare anything in the namespace std
...........
Google,
............
SEI Cert,
................
Clang-Tidy,
............
CoreCpp
Do not use using namespace declarations of any kind to import names in the
std namespace
..........
Webkit
Do not use
inline namespaces
..........
Google
21/78
using namespace Directive
Avoid using namespace -directives, especially at global scope
........
LLVM,
..........
Google,
..........
Webkit,
..........
Unreal,
....
Hic,
......
µOS,
............
CoreCpp
# include <cmath> // if 'header.hpp' contains
# include "header.hpp" // 'using namespace std;'
auto f(float a) { return abs(a) * 2; } // f(3.5) returns 7 instead of 6
Limit using namespace -directives at local scope and prefer explicit
namespace entities declarations
..........
Google,
..........
Unreal,
.....
Hic,
................
Clang-Tidy
using namespace is allowed in implementation files in nested namespaces
..........
Webkit
22/78
Anonymous/Unnamed Namespace
Avoid anonymous namespaces/ static in headers
...........
Google,
......
µOS,
............
SEI Cert,
................
Clang-Tidy,
............
CoreCpp
anonymous namespace vs. static
- anonymous namespaces instead of static everywhere
....
Hic,
...............
Clang-Tidy,
............
CoreCpp
- anonymous namespaces only for struct / class declaration, static
otherwise (easy identification)
........
LLVM,
...........
Mozilla,
......
µOS
Anonymous namespaces and static in source files:
Items local to a source file (e.g. .cpp) file should be wrapped in an anonymous
namespace/marked static . Anonymous namespaces/ static restrict symbols visibility
to the translation unit, improving function call cost and reduce the size of entry point
tables
..........
Google,
.............
Chromium,
...........
CoreCpp,
.....
Hic,
......
µOS
23/78
Namespace and Class Design
All helper functions and operators of a class need to belong to the same
namespace of the class
Prefer free functions in namespaces instead of classes, avoid global scope
functions
..........
Google
Namespaces & Interface Principle
24/78
Style 1/2
The content of namespaces is not indented
........
LLVM,
..........
Google,
..........
Webkit
namespace ns {
void f() {}
}
Close namespace declarations
.........
LLVM,
..........
Google,
..........
Webkit,
................
Clang-Tidy
} // namespace <namespace_identifier>
} // namespace (for anonymous namespaces)
Namespaces should have unique names based on the project name
..........
Google
25/78
Style 2/2
Prefer single-line nested namespace declarations ns1::ns2 C++17
...........
Google,
...........
Mozilla
Minimize use of nested namespaces
.............
Chromium
Namespaces can match hierarchy with file system hierarchy for consistency
include/
my project/
core.hpp
detail/
helper.hpp
namespace project name::detail
Using namespaces effectively
26/78
Modern C++
Modern C++
Use C++ over pure C and
use modern C++ wherever possible
27/78
Modern C++ Keywords 1/3
Use constexpr C++11 variables to define true constants (instead of macro)
..........
Google,
..........
Webkit,
............
CoreCpp
1
,
............
CoreCpp
2
Use consteval C++20 function to ensure compile-time evaluation
..........
Google
Use constinit C++20 to ensure constant initialization for non-constant
variables
..........
Google
static assert compile-time assertion
..........
Unreal,
.....
Hic
28/78
Modern C++ Keywords 2/3
Prefer enum class C++11 instead of plain enum C++11
.........
Unreal,
......
µOS,
............
CoreCpp
Use auto C++11 to avoid type names that are noisy, obvious, or
unimportant
auto array = new int[10];
auto var = static cast<int>(var);
........
LLVM,
..........
Google,
....
Hic,
................
Clang-Tidy,
............
CoreCpp
(only for lambdas, iterators, template expressions)
..........
Unreal
nullptr C++11 instead of 0 or NULL for pointers
..........
Google,
..........
Unreal,
..........
Webkit,
...........
Mozilla,
....
Hic,
.....
µOS,
................
Clang-Tidy,
............
CoreCpp
29/78
Modern C++ Keywords 3/3
Use the explicit keyword for conversion operators C++11 and
constructors. Do not define implicit conversions
...........
Google,
...........
Mozilla,
.....
µOS
Use using C++11 instead typedef
..........
Mozilla,
................
Clang-Tidy,
............
CoreCpp
Avoid throw function specifier. Use noexcept C++11 instead
.... . .. . .. ..
Microsoft Blog
30/78
Modern C++ Features 1/2
lambda expression C++11
..........
Unreal
move semantic C++11
..........
Unreal
Use range-based for loops whenever possible C++11
.........
LLVM,
..........
Unreal,
...............
Clang-Tidy,
............
CoreCpp
1
,
............
CoreCpp
2
,
............
CoreCpp
3
Prefer uniform (brace) initialization C++11 when it cannot be confused with
std::initializer list
.............
Chromium
31/78
Modern C++ Features 2/2
static cast , reinterpret cast , const cast , std::bit cast C++20,
instead of old style cast (type)
........
LLVM,
..........
Google,
......
µOS,
.....
Hic,
................
Clang-Tidy
Use [[deprecated]] C++14 / [[noreturn]] C++11 / [[nodiscard]]
C++17 to indicate deprecated functions / that do not return / result should not
be discarded
................
Clang-Tidy
Use = delete C++11 to mark deleted functions
Replace SFINAE with concepts C++20
................
Clang-Tidy
Use structure binding C++17
Use designated initializers C++20
................
Clang-Tidy
32/78
Modern C++ Features - Class 1/2
Always use override C++11 and final function member keywords
..........
Google,
..........
Webkit,
...........
Mozilla,
..........
Unreal,
....
Hic,
................
Clang-Tidy,
............
CoreCpp
Use = default C++11 constructors
33/78
Modern C++ Features - Class 2/2
Use braced direct-list-initialization or copy-initialization C++11 for setting
default data member value. Avoid initialization in constructors if possible
..........
Unreal
struct A {
int x = 3; // copy-initialization
int x { 3 }; // direct-list-initialization
};
Replaces explicit calls to the constructor in a return with a braced initializer list
................
Clang-Tidy
Foo bar() { return Foo(3); }
Foo bar() { return {3}; }
34/78
Modern C++ Library
Avoid C-Style memory management malloc()/free() and use new/delete
............
CoreCpp,
................
Clang-Tidy
Except int , Use fixed-width integer type C++11 (e.g. int64 t , int8 t ,
etc.)
.............
Chromium,
..........
Unreal,
..........
Google,
.....
Hic,
......
µOS,
................
Clang-Tidy
Use std::print C++23
................
Clang-Tidy
Uses modern type traits C++17
................
Clang-Tidy
std::is_integral<T>::value; // --> std::is integral v
std::make_signed<unsigned>::type; // --> std::std::make signed t
35/78
Maintainability
Maintainability 1/3
Document code (See code documentation section)
Don’t optimize without reason
............
CoreCpp
Address compiler warnings. Compiler warning messages mean something is
wrong
..........
Unreal
Compile-time and link-time errors should be preferred over run-time errors
......
µOS,
............
CoreCpp
36/78
Maintainability 2/3
Avoid RTTI (dynamic cast) and exceptions
........
LLVM,
..........
Google
1
,
...........
Google
2
,
...........
Mozilla
1
,
...........
Mozilla
2
,
.....
Hic
Do not use reserved names
............
SEI Cert,
................
Clang-Tidy
- double underscore followed by any character var
- single underscore followed by uppercase VAR
The goto statement shall not be used
......
µOS,
................
Clang-Tidy
Code that is not used (commented out) should be deleted
.....
µOS
Code should not include unnecessary constructs: variables, types, unreachable
code
.....
µOS
37/78
Maintainability 3/3
Do not depend on the order of evaluation for side effects
............
SEI Cert
f(i++, i++);
a[i++] = i;
Do not perform assignments in conditional statements
............
SEI Cert,
................
Clang-Tidy
if (a = b)
Prefer sizeof(variable/value) instead of sizeof(type)
..........
Google
Avoid octal numbers, e.g. int v = 0010; //8
.....
Hic,
.....
µOS
38/78
Maintainability - Code Comprehension
Write self-documenting code
e.g. (x + y - 1) / y ceil div(x, y)
..........
Unreal
Use symbolic names instead of literal values in code (don’t use magic numbers)
....
Hic,
................
Clang-Tidy,
............
CoreCpp
double area1 = 3.14 * radius * radius; // BAD
constexpr auto Pi = 3.14; // correct
double area2 = Pi * radius * radius;
Use parentheses in expressions to specify the intent of the expression,
especially with mixed operators
....
Hic,
.....
µOS,
................
Clang-Tidy,
............
CoreCpp
int r = i + j * k - 4 / 5; // BAD
if ((i != 0) && (j != 0) || (k != 0)) // BAD
39/78
Maintainability - Constants 2/3
Enforce const -correctness
..........
Unreal
Pass function arguments by const pointer or reference
............
CoreCpp
Function members
............
CoreCpp
Use const iteration over containers if the loop isn’t intended to modify the
container
Declare an object const or constexpr unless you want to modify its value
later on
............
CoreCpp
1
,
...........
CoreCpp
2
,
..........
Unreal
but don’t
const all the things
1
,
............
CoreCpp
Pass by- const value: almost useless (copy), ABI break
const return: useless (copy)
...............
Clang-Tidy,
..........
Unreal
const data member: disable assignment and copy constructor
const local variables: verbose, rarely effective
1
Don’t const all the things
40/78
Maintainability - Functions
Use assert to document preconditions and assumptions
.........
LLVM,
............
CoreCpp
Ensure that all statements are reachable for at at least one combination of
function inputs
.....
Hic
Prevent using functions that don’t accept nullptr
............
CoreCpp
void f(void*);
void f(nullptr) = delete;
// f(nullptr) // compile error
41/78
Maintainability - Object Semantic
Prefer RAII instead of manual resource management
............
CoreCpp
1
,
............
CoreCpp
2
void f(char* name) {
FILE* input = fopen(name, "r"); // use "ifstream input {name};" instead
if (something) return; // BAD: if something == true,
// ... // a file handle is leaked
fclose(input);
}
Never transfer ownership by a raw pointer (T*) or reference (T&) . Use
object semantics, unique ptr , etc.
............
CoreCpp
Avoid singletons. Use a static member function named singleton() to
access the instance of the singleton instead of a free function
..........
Webkit,
............
CoreCpp
42/78
Maintainability - Template and Deduction
Avoid complicated template programming
..........
Google
Be aware of bug-prone deductions
template<typename T, int N>
void f(const T&);
template<typename T>
void f(T); // same of f(T*)
int array[3];
f(array); // call the second funtion, not f(T&)
43/78
Maintainability - Library
Do not pass an array as a single pointer. Prefer std::span , std::mdspan
............
CoreCpp
Prefer core-language features over library facilities, e.g. uint8 t vs.
std::byte
Prefer std::array over plain array. It can be also used to return multiple values
of the same type from a function
............
CoreCpp
1
,
............
CoreCpp
2
Use std::string view to refer to character sequences
............
CoreCpp
Prefer core-language features over library facilities
44/78
Portability
Portability 1/2
Ensure ISO C++ compliant code. Do not use non-standard extensions
see -Wpedantic
.....
Hic,
..........
Google
1
,
..........
Google
2
,
......
µOS,
............
CoreCpp
Do not use deprecated C++ features, or asm declarations, e.g. register ,
attribute , throw (function qualifier)
.....
Hic
Do not use reinterpret cast or union for type punning
Prefer std::bit cast or std::memcpy
............
CoreCpp
1
,
............
CoreCpp
2
,
.....
Hic
Except int , use fixed-width integer type (e.g. int64 t , int8 t , etc.)
.............
Chromium,
..........
Unreal,
..........
Google,
.....
Hic,
......
µOS,
................
Clang-Tidy
45/78
Portability 2/2
Don’t use long double
Do not use UTF characters* for portability, prefer ASCII
..........
Google,
.....
µOS
If UTF is needed, prefer UTF-8 encoding for portability
..........
Google,
.............
Chromium
Use the same line ending (e.g. '\n' ) for all files
...........
Mozilla,
.............
Chromium
* Trojan Source attack for introducing invisible vulnerabilities
46/78
Naming
Naming
“Beyond basic mathematical aptitude, the difference be-
tween good programmers and great programmers is verbal
ability”
Marissa Mayer
47/78
General Notes on Naming 1/2
Naming is hard. Most of the time, code is shared with other developers. It is
worth spending a few seconds to find the right name
Think about the purpose to choose names
Adopt names commonly used in real contexts (outside the code)
Don’t use the same name for different things. Use a specific name everywhere
Prefer single English word to implementation-focused, e.g.
UpdateConfigFile() save()
Use natural word pair, e.g. create()/destroy() , open()/close() ,
begin()/end() , source()/destination()
.....
µOS
48/78
General Notes on Naming 2/2
Don’t overdecorate, e.g. Base/Impl , Factory/Singleton
Don’t list the content, e.g. NameAndAddress ContactInfo
Don’t repeat class/enum names, e.g. Employee::EmployeeName
Avoid temporal attributes, e.g. PreLoad() , PostLoad()
Use adjectives to enrich a name, e.g. Name FullName , Salary
AnnualSalary
Naming is Hard: Let’s Do Better, CppCon 2019, Kate Gregory
49/78
Entities Naming 1/2
Abbreviations are generally bad, longer names are better in most cases (don’t
be lazy)
.....
µOS
Use whole words, except in the rare case where an abbreviation would be more
canonical and easier to understand, e.g. tmp
..........
Webkit
Avoid short and very long names. Remember that the average word length in
English is 4.8
................
Clang-Tidy
50/78
Entities Naming 2/2
Avoid names that are easily misread: similar or hard to pronounce
............
CoreCpp
Avoid ambiguous characters, o/O/0 , I/l/1 , s/S/5 , Z/2 , N/n/h , B/8
e.g. hel1o
....
Hic,
......
µOS,
............
CoreCpp
Do not abbreviate by deleting letters within a word
..........
Google
If you are naming something that is analogous to an existing C or C++ entity
then you can follow the existing naming convention scheme
..........
Google
51/78
Variables Naming 1/2
The length of a variable should be proportional to the size of the scope that
contains it. For example, i is fine within a loop
..........
Google,
............
CoreCpp
1
,
............
CoreCpp
2
Names can be made singular or plural depending on whether they hold a single
value or multiple values, thus arrays and collections should be plural
.....
µOS
int value;
int values[N];
52/78
Variables Naming 2/2
Use common loop variable names
- i, j, k, l used in order
- it for iterators
Make literals readable
............
CoreCpp
auto c = 299'792'458; // digit separation
auto interval = 100ms; // using <chrono>
53/78
Functions Naming
Should be descriptive verb (as they represent actions)
..........
Webkit
Should describe their action or effect instead of how they are
implemented, e.g. partial sort() top n()
Functions that return boolean values should start with boolean verbs, like
is, has, should, does
.....
µOS
empty() is empty()
54/78
Naming Style Conventions
Capital Uppercase first word letter (sometimes called Pascal style or uppercase
Camel style) (less readable, shorter names)
CapitalStyle
Camel-Back Uppercase first word letter except the first one (less readable, shorter
names)
camelBack
Snake Lower case words separated by single underscore (good readability, longer
names)
snake_style
Macro Upper case words separated by single underscore (sometimes called All
Capitalized or Screaming style) (best readability, longer names)
MACRO_STYLE
55/78
Naming Style Conventions - Variables/Constant
Variable Variable names should be nouns
Capital style e.g. MyVar
........
LLVM,
..........
Unreal
Snake style e.g. my var
...........
Google,
..........
Webkit, Std,
......
µOS
Global variable with g prefix, e.g. gVar
...........
Mozilla
Arguments with a prefix, e.g. aVar
...........
Mozilla
Constant Capital style + k prefix,
..........
Google,
...........
Mozilla
e.g. kConstantVar
Snake style e.g. my var
......
µOS
Macro style e.g. CONSTANT VAR OpenStack
56/78
Naming Style Conventions - Function
Camel-back style, e.g. myFunc()
........
LLVM
Capital style, e.g. MyFunc()
..........
Google,
.............
Chromium,
...........
Mozilla,
..........
Unreal
Snake style, e.g. my func()
..........
Webkit, Std,
.....
µOS
Snake style for accessor and mutator methods
..........
Google,
.............
Chromium
57/78
Naming Style Conventions - Enum/Namespace
Enum Capital style + k
..........
Google
e.g. enum MyEnum { kEnumVar1, kEnumVar2 }
e prefix
...........
Mozilla
e.g. enum MyEnum { eVar1, eVar2 }
Capital style
........
LLVM,
..........
Webkit,
..........
Unreal
e.g. enum MyEnum { EnumVar1, EnumVar2 }
Snake style
......
µOS
e.g. enum MyEnum { enum var1, enum var2 }
Type Should be nouns
Capital style (including classes, structs, enums, typedefs, template, etc.)
e.g. HelloWorldClass
........
LLVM,
...........
Google,
..........
Webkit,
..........
Unreal
Snake style µOS (class), Std
58/78
Naming Style Conventions - Type/Macro/File
Namespace Snake style, e.g. my namespace
...........
Google,
........
LLVM, Std
Capital style, e.g. MyNamespace
..........
Webkit,
..........
Unreal
Macro Macro style, e.g.
MY MACRO
..........
Google, Std,
..........
Unreal,
..........
Webkit,
...........
Mozilla,
...........
CoreCpp
Macro style should be used only for macros
............
CoreCpp
1
,
............
CoreCpp
2
,
............
CoreCpp
3
,
...........
CoreCpp
4
File Snake style ( my file )
..........
Google
Capital style ( MyFile ), could lead Windows/Linux conflicts
........
LLVM
59/78
Personal Comment
Personal Comment: Macro style needs to be used only for macros to avoid subtle bugs. I prefer
snake style for almost everything because it has the best readability. On the other hand, I don’t want
to confuse typenames and variables, so I use camel style for the former ones. Finally, I also use camel
style for compile-time constants because they are very relevant in my work and I need to quickly
identify them
60/78
Enforcing Naming Styles
Naming style conventions can be also enforced by using tools like
clang-tidy: readability-identifier-naming
.clang-tidy configuration file
Checks: 'readability-identifier-naming'
HeaderFileExtensions: ['', 'h','hh','hpp','hxx']
ImplementationFileExtensions: ['c','cc','cpp','cxx']
CheckOptions:
readability-identifier-naming.ClassCase: 'lower_case'
readability-identifier-naming.MacroDefinitionCase: 'UPPER_CASE'
class MyClass {}; // before
# define my_macro
class my_class {}; // after
# define MY_MACRO
61/78
Readability and
Formatting
Horizontal Spacing 1/3
Limit line length (width) to be at most 80 characters long (or 100, or 120)
help code view on a terminal
........
LLVM (80),
..........
Google (80),
.....
µOS(120)
Personal Comment: I was tempted several times to use a line length > 80 to reduce the
number of lines, and therefore improve the readability. Many of my colleagues use split-screens or
even the notebook during travels. A line length of 80 columns is a good compromise for everyone
Is the 80 character limit still relevant in times of widescreen monitors?
Linus Torvalds on 80 column limit
62/78
Horizontal Spacing 2/3
Use always the same indentation style
- tab 2 spaces
..........
Google,
......
µOS
- tab 4 spaces
........
LLVM,
..........
Webkit,
....
Hic, Python
- (actual) tab = 4 spaces
..........
Unreal
Personal Comment: I worked on projects with both two and four-space tabs. I observed less
bugs due to indentation and better readability with four-space tabs. ’Actual tabs’ breaks the line
length convention and can introduce tabs in the middle of the code, producing a very different
formatting from the original one
Style Guide for Python Code, Guido van Rossum,, Barry Warsaw, Alyssa Coghlan
63/78
Horizontal Spacing 3/3
Separate commands, operators, etc., by a space
........
LLVM,
..........
Google
1
,
..........
Google
2
,
..........
Webkit,
............
CoreCpp
if(a*b<10&&c) // BAD
if (a * c < 10 && c) // good
Prefer consecutive alignment
int var1 = ...
long long int longvar2 = ...
Do not place spaces around unary operators i ++
..........
Webkit
Never put trailing white space or tabs at the end of a line
..........
Google
64/78
Pointers/References
Declaration of pointer/reference variables or arguments may be placed with the
asterisk/ampersand adjacent to either the type or to the variable name for all
symbols in the same way
..........
Google
char* c;
..........
Webkit,
.............
Chromium,
.........
Unreal,
............
CoreCpp
char *c;
char * c;
Pointer and reference types and variables have no space after the * or &
..........
Google
char * v; // BAD
auto & v = w; // BAD
* p = 3; // BAD
v. x + 2; // BAD
x = r-> y; // BAD
65/78
Vertical Spacing 1/2
Do not write excessive long file
Each statement should get its own line
..........
Webkit,
......
µOS,
............
CoreCpp
1
,
............
CoreCpp
2
,
....
Hic,
..........
Google
x++;
y++;
if (condition)
doIt();
What is your threshold for a long source file?
66/78
Vertical Spacing 2/2
Minimize the number of empty rows. The more code that fits on one screen,
the easier it is to follow and understand the control flow of the program
..........
Google
Close files with a blank line
..........
Unreal
67/78
Braces 1/2
Multi-lines statements and complex conditions require curly braces. Use an
additional boolean variable if possible
..........
Google
1
,
..........
Google
2
,
..........
Webkit
if (c1 && ... &&
c2 && ...) { // correct
<statement>
}
Curly braces are not required for single-line statements ( for, while, if )
........
LLVM,
..........
Google,
..........
Webkit
if (c1) { // not mandatory
<statement>
}
Always use brace for all control statements
...........
Mozilla,
.............
Chromium,
.....
µOS
68/78
Braces 2/2
Use always the same style for braces
Same line, aka Kernigham & Ritchie
...........
Google
1
,
...........
Google
2
..........
Webkit (function only),
............
CoreCpp (expect for function)
Its own line, aka Allman
..........
Unreal,
..........
Webkit (class, namespace, control flow)
//Kernigham & Ritchie
int main() {
code
}
// Allman
int main()
{
code
}
Personal Comment: C++ is a very verbose language. Same line convention helps to keep the
code more compact, improving the readability
69/78
Type Decorators
The same concept applies to const
const int* West notation
..........
Google,
............
CoreCpp
int const* East notation Autosar (Rule A7-1-3)
Personal Comment: I prefer West notation to prevent unintentional cv-qualify
(const/volatile) of a reference or pointer types char &const p , see DCL52-CPP. Never
qualify a reference type with const or volatile
Prefer the common order of declaration static constexpr int var
.....
µOS
70/78
Reduce Code Verbosity
Use the short name version of built-in types, e.g.
..........
Webkit
unsigned instead of unsigned int
long long instead of long long int
Don’t const all the things. Avoid Pass by- const , const return, const
data member, const local variables
Don’t const all the things
71/78
Other Issues
Write all code in English, comments included
Use true , false for boolean variables instead numeric values 0, 1
..........
Webkit,
................
Clang-Tidy
Boolean expressions at the same nesting level that span multiple lines should have
their operators on the left side of the line instead of the right side
..........
Webkit
return attribute.name() == srcAttr
|| attribute.name() == lowsrcAttr;
Final note: Most of the formatting guidelines can be forced by using clang-tidy
and clang-format
72/78
Code
Documentation and
Comments
Programmers vs. Documentation
73/78
Code Documentation
Comment what the code does and why
.........
LLVM,
............
CoreCpp
- Avoid how it is implemented at low level
- All files should report a brief description of their purpose
- Describe classes and methods
Don’t say in comments what can be clearly stated in code
............
CoreCpp
Document each entity (functions, classes, namespaces, definitions, etc.) and
only in the declarations, e.g. header files
74/78
Function Documentation
The first sentence (beginning with @brief ) is used as an abstract
Document the inputs: @param[in] , @param[in,out] , , and template
parameters @tparam
Document outputs: return value @return and output parameters
@param[out]
...........
Google,
..........
Unreal
Document preconditions: input ranges, impossible values (e.g. nullptr ),
status/return values meaning
..........
Unreal
Document program state changes (e.g. static ), arguments with lifetime
beyond the duration of the method call (e.g. constructors), performance
implications
...........
Google,
..........
Unreal
75/78
Comment Syntax
Prefer // comment instead of /* */ prevent bugs and allow string-search
tools like grep to identify valid code lines
.....
Hic,
.....
µOS
Use the same style of comment // , /// , //* , //! , etc.
Multiple lines and single line comments can have different styles
/**
* comment1
* comment2
*/
/// single line
µOS++ Doxygen style guide link
Teaching the art of great documentation, by Google
76/78
Other Comment Issues
Use anchors for indicating special issues: TODO , FIXME , BUG , etc.
..........
Webkit,
.............
Chromium
Only one space between statement and comment
..........
Webkit
77/78
File Documentation
Any file start with a license (even scripts)
..........
Google,
........
LLVM
Each file should include
- @author name, surname, affiliation, email
- @date e.g. year and month
@file the purpose of the file
in both header and source files
78/78