Modern C++
Programming
16. Code Conventions
Part II
Federico Busato
2026-01-06
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
Literals
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 my_project::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)) // correct
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 least one combination of function
inputs
.....
Hic
• Prevent using functions that don’t accept nullptr
............
CoreCpp
# include <cstddef> // std::nullptr_
void f(void*);
void f(std::nullptr_t) = 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
• 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
Literals
※ 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
• Use uppercase for post-fix literals, 1234L , 1234ULL
............
SEI Cert
• Hexadecimal constants should be uppercase, 0x1BA7
.......................
Autosar, A2-13-5
(personal) exception: do not mix with uppercase for post-fix literals, 0x1BACULL
• Make literals readable
............
CoreCpp
auto c = 299'792'458; // digit separation
auto interval = 100ms; // using <chrono>
52/78
Variables Naming
∗ 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];
• Use common loop variable names
- i, j, k, l used in order
- it for iterators
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 (C98 compatibility)
..........
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