0% found this document useful (0 votes)
28 views95 pages

Not An Engineering

The document discusses coding conventions and styles for C++ projects. It covers common project organization structures, naming conventions, formatting styles and other guidelines to write clear, readable and maintainable C++ code. It also provides references to style guides from organizations like Google, LLVM, Mozilla and others.

Uploaded by

rosekavalierhc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views95 pages

Not An Engineering

The document discusses coding conventions and styles for C++ projects. It covers common project organization structures, naming conventions, formatting styles and other guidelines to write clear, readable and maintainable C++ code. It also provides references to style guides from organizations like Google, LLVM, Mozilla and others.

Uploaded by

rosekavalierhc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 95

Modern C++

Programming
13. Code Conventions

Federico Busato
2023-11-14
Table of Context

1 C++ Project Organization


Project Directories
Project Files
“Common” Project Organization Notes
Alternative - “Canonical” Project Organization

2 Coding Styles and Conventions


Coding Styles

3 #include
1/80
Table of Context

4 Macro and Preprocessing

5 namespace

6 Variables

7 Functions

8 Structs and Classes

2/80
Table of Context

9 Control Flow
10 Modern C++ Features
11 Maintainability
12 Naming
13 Readability and Formatting
14 Code Documentation

3/80
C++ Project
Organization
“Common” Project Organization

4/80
Project Directories 1/2

Fundamental directories
include Project public header files
src Project source files and private headers
test (or tests) Source files for testing the project

Empty directories
bin Output executables
build All intermediate files
doc (or docs) Project documentation
5/80
Project Directories 2/2

Optional directories
submodules Project submodules

third party (less often deps/external/extern) dependencies or external


libraries

data (or extras) Files used by the executables or for testing

examples Source files for showing project features

utils (or tools, or script) Scripts and utilities related to the project

cmake CMake submodules (.cmake)


6/80
Project Files

LICENSE Describes how this project can be used and distributed

README.md General information about the project in Markdown format *

CMakeLists.txt Describes how to compile the project

Doxyfile Configuration file used by doxygen to generate the documentation (see


next lecture)

others .gitignore, .clang-format, .clang-tidy, etc.

* Markdown is a language with a syntax corresponding to a subset of HTML tags


github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet 7/80
Readme and License

README.md

• README template:
- Embedded Artistry README Template
- Your Project is Great, So Let’s Make Your README Great Too

LICENSE

• Choose an open source license:


choosealicense.com
• License guidelines:
Why your academic code needs a software license

8/80
File extensions

Common C++ file extensions:


• header .h .hh .hpp .hxx

• header implementation .i.h .i.hpp -inl.h .inl.hpp


(1) separate implementation from interface for inline functions and templates
(2) keep implementation “inline” in the header file

• source/implementation .c .cc .cpp .cxx

Common conventions:
• .h .c .cc Google
• .hh .cc
• .hpp .cpp
• .hxx .cxx 9/80
Common Rules

The file should have the same name of the class/namespace that they
implement

• class MyClass
my class.hpp (MyClass.hpp)
my class.i.hpp (MyClass.i.hpp)
my class.cpp (MyClass.cpp)

• namespace my np
my np.hpp (MyNP.hpp)
my np.i.hpp (MyNP.i.hpp)
my np.cpp (MyNP.cpp)

10/80
“Common” Project Organization Notes

• Public header(s) in include/

• source files, private headers, header implementations in src/ directory

• The main file (if present) can be placed in src/ and called main.cpp

• Code tests, unit and functional (see C++ Ecosystem I slides), can be
placed in test/ , or unit tests can appear in the same directory of the
component under test with the same filename and include .test suffix,
e.g. my file.test.cpp

11/80
“Common” Project Organization Example

<project name>
include/ README.md
public header.hpp CMakeLists.txt
src/ Doxyfile
private header.hpp LICENSE
templ class.hpp build/ (empty)
templ class.i.hpp bin/ (empty)
(template/inline functions) doc/ (empty)
templ class.cpp test/
(specialization) my test.hpp
subdir/ my test.cpp
my file.cpp ...
12/80
“Common” Project Organization - Improvements

The “common” project organization can be <project name>


improved by adding the name of the project include/
as subdirectory of include/ and src/ <project name>/
public header.hpp
This is particularly useful when the project
src/
is used as submodule (part of a larger
<project name>/
project) or imported as an external library
private file.hpp
The includes now look like:
# include <my_project/public_header.hpp>

13/80
Alternative - “Canonical” Project Organization 1/2

• Header and source files (or module interface and implementation files) are next
to each other (no include/ and src/ split)

• Headers are included with <> and contain the project directory prefix, for
example, <hello/hello.hpp> (no need of "" syntax)

• Header and source file extensions are .hpp / .cpp ( .mpp for module
interfaces). No special characters other than and - in file names with . only
used for extensions

• A source file that implements a module’s unit tests should be placed next to that
module’s files and be called with the module’s name plus the .test second-level
extension

• A project’s functional/integration tests should go into the tests/ subdirectory 14/80


Alternative - “Canonical” Project Organization 2/2

<project name> (v1) <project name> (v2)


<project name>/ <project name>/
public header.hpp public header.hpp
private header.hpp private/
my file.cpp private header.hpp
my file.mpp my internal file.cpp
my file.test.cpp my internal file.test.cpp
tests/ tests/
my functional test.cpp my functional test.cpp
build/ build/
doc/ doc/
... ...
15/80
References

• Kick-start your C++! A template for modern C++ projects

• The Pitchfork Layout

• Canonical Project Structure

16/80
Coding Styles and
Conventions
Overview

“one thing people should remember is


there is what you can do in a language and
what you should do”
Bjarne Stroustrup

17/80
Overview

Most important rule:


BE CONSISTENT!!

“The best code explains itself”


Google

18/80
Overview

“80% of the lifetime cost of a piece of


software goes to maintenance”
Unreal Engine

19/80
Code Quality

“The worst thing that can happen to a code base is size”


— Steve Yegge

20/80
Bad Code

How my code looks like for other people?

21/80
abstrusegoose.com/432
Coding Styles 1/3

Coding styles are common guidelines to improve the readability, maintainability,


prevent common errors, and make the code more uniform

• LLVM Coding Standards llvm.org/docs/CodingStandards.html

• Google C++ Style Guide google.github.io/styleguide/cppguide.html

• Webkit Coding Style


webkit.org/code-style-guidelines

• Mozilla Coding Style


firefox-source-docs.mozilla.org

22/80
Coding Styles 2/3

• Chromium Coding Style


chromium.googlesource.com
c++-dos-and-donts.md
• Unreal Engine - Coding Standard
docs.unrealengine.com/en-us/Programming
• µOS++
micro-os-plus.github.io/develop/coding-style
micro-os-plus.github.io/develop/naming-conventions
• High Integrity C++ Coding Standard
www.perforce.com/resources
• CERT C++ Secure Coding
wiki.sei.cmu.edu 23/80
Coding Styles 3/3

More educational-oriented guidelines


• C++ Guidelines
isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

Critical system coding standards


• Misra - Coding Standard
www.misra.org.uk

• Autosar - Coding Standard


www.misra.org.uk

• Joint Strike Fighter Air Vehicle


www.perforce.com/blog/qac/jsf-coding-standard-cpp
24/80
Legend

※ → Important!
Highlight potential code issues such as bugs, inefficiency, and can compromise
readability. Should not be ignored

∗ → Useful
It is not fundamental but it emphasizes good practices and can help to prevent
bugs. Should be followed if possible

• → Minor / Obvious
Style choice or not very common issue

25/80
#include
#include 1/5

※ Every include must be self-contained


- include every header you need directly
- do not rely on recursive #include
- the project must compile with any include order
LLVM, Google, Unreal, µOS++, Core

∗ Include as less as possible, especially in header files


- do not include unneeded headers
- minimize dependencies
- minimize code in headers (e.g. use forward declarations)
LLVM, Google, Chromium, Unreal, Hic, µOS++

26/80
#include 2/5

Order of #include LLVM, WebKit, Core

(1) Main module/interface header, if exists (it is only one)

• space

(2) Local project includes (in lexicographic order)

• space

(3) System includes (in lexicographic order)

Note: (2) and (3) can be swapped Google


System includes are self-contained, local includes might not

27/80
#include 3/5

Project includes LLVM, Google, WebKit, Hic, Core


∗ Use "" syntax

∗ Should be absolute paths from the project include root


e.g. #include "directory1/header.hpp"

System includes LLVM, Google, WebKit, Hic


∗ Use <> syntax
e.g. #include <iostream>

28/80
#include 4/5

※ Always use an include guard

• macro include guard vs. #pragma once


- Use macro include guard if portability is a very strong requirement
LLVM, Google, Chromium, Core
- #pragma once otherwise WebKit, Unreal

• #include preprocessor should be placed immediately after the header comment


and include guard LLVM

Forward declarations vs. #includes


• Prefer forward declaration: reduce compile time, less dependency Chromium

• Prefer #include : safer Google29/80


#include 5/5

∗ Use C++ headers instead of C headers:


<cassert> instead of <assert.h>
<cmath> instead of <math.h>, etc.

• Report at least one function used for each include


<iostream> // std::cout, std::cin

# include "my_class.hpp" // MyClass


[ blank line ]
# include "my_dir/my_headerA.hpp" // npA::ClassA, npB::f2()
# include "my_dir/my_headerB.hpp" // np::g()
[ blank line ]
# include <cmath> // std::fabs()
# include <iostream> // std::cout
# include <vector> // std::vector

30/80
Macro and
Preprocessing
Macro and Preprocessing 1/4

※ Avoid defining macros, especially in headers Google


- Do not use macro for enumerators, constants, and functions
WebKit, Google

※ Use a prefix for all macros related to the project MYPROJECT MACRO
Google, Unreal

※ #undef macros wherever possible Google


- Even in the source files if unity build is used (merging multiple source files to
improve compile time)

31/80
Macro and Preprocessing 2/4

※ Always use curly brackets for multi-line macro


# define MACRO \
{ \
line1; \
line2; \
}

※ Always put macros after #include statements Hic

• Put macros outside namespaces as they don’t have a scope

32/80
Macro and Preprocessing - Style 3/4

• Close #endif with the respective condition of the first #if


# if defined(MACRO)
...
# endif // defined(MACRO)

• The hash mark that starts a preprocessor directive should always be at the
beginning of the line Google
# if defined(MACRO)
# define MACRO2
# endif

33/80
Macro and Preprocessing - Style 4/4

• Place the \ rightmost for multi-line macro


# define MACRO2 \
macro_def...

• Prefer #if defined(MACRO) instead of #ifdef MACRO


Improve readability, help grep-like utils, and it is uniform with multiple conditions
# if define(MACRO1) && defined(MACRO2)

34/80
namespace
Namespace 1/3

※ Avoid using namespace -directives at global scope


LLVM, Google, WebKit, Unreal, Hic, µOS++

∗ Limit using namespace -directives at local scope and prefer explicit


namespace specification Google, WebKit, Unreal

※ Always place code in a namespace to avoid global namespace pollution


Google, WebKit

35/80
Namespace- Anonymous 2/3

∗ Avoid anonymous namespaces in headers Google, Cert

• anonymous namespace vs. static


- Prefer anonymous namespaces instead of static variables/functions
Google, Core
- Use anonymous namespaces only for inline class declaration, static otherwise
LLVM, static

∗ Anonymous namespaces and source files:


Items local to a source file (e.g. .cpp) file should be wrapped in an anonymous
namespace. While some such items are already file-scope by default in C++, not all are;
also, shared objects on Linux builds export all symbols, so anonymous namespaces (which
restrict these symbols to the compilation unit) improve function call cost and reduce the
size of entry point tables Chromium, Core, Hic
36/80
Namespace - Style 3/3

• The content of namespaces is not indented LLVM, Google, WebKit


namespace ns {

void f() {}

• Close namespace declarations LLVM, Google


} // namespace <namespace_identifier>
} // namespace (for anonymous namespaces)

37/80
Variables
Variable 1/3

※ Place a variables in the narrowest scope possible, and always initialize


variables in the declaration
Google, Isocpp, Mozilla, Hic, muOS, Cert

∗ Avoid static (non-const) global variables LLVM, Google, Core, Hic

• Use assignment syntax = when performing “simple” initialization Chromium

38/80
Variable - Arithmetic Types 2/3

※ Use fixed-width integer type (e.g. int64 t , int8 t , etc.)


Exception: int and unsigned Google, Unreal

∗ size t vs. int64 t


- Use size t for object and allocation sizes, object counts, array and pointer offsets,
vector indices, and so on. (integer overflow behavior for signed types is undefined)
Chromium
- Use int64 t instead of size t for object counts and loop indices Google

• Use brace initialization to convert constant arithmetic types


(narrowing) e.g. int64 t{MyConstant} Google

∗ Use true , false for boolean variables instead numeric values 0, 1 WebKit
39/80
Variables - Arithmetic Types 3/3

※ Do not shift ≪ signed operands Hic, Core, µOS

※ Do not directly compare floating point == , < , etc. Hic

※ Use signed types for arithmetic Core

Style:

• Use floating-point literals to highlight floating-point data types, e.g. 30.0f


WebKit (opposite)

• Avoid redundant type, e.g. unsigned int , signed int WebKit

40/80
Functions
Functions 1/3

∗ Limit overloaded functions. Prefer default arguments Google, Core

∗ Split up large functions into logical sub-functions for improving readability and
compile time Unreal, Google, Core

• Use inline only for small functions (e.g. < 10 lines) Google, Hic

※ Never return pointers for new objects. Use std::unique ptr instead
Chromium, Core
int* f() { return new int[10]; } // wrong!!
std::unique_ptr<int> f() { return new int[10]; } // correct

41/80
Functions - Parameters 2/3

※ Prefer pass by-reference instead by-value except for raw arrays and built-in
types WebKit

∗ Pass function arguments by const pointer or reference if those arguments


are not intended to be modified by the function Unreal

∗ Do not pass by-const-value for built-in types, especially in the declaration


(same signature of by-value)

∗ Prefer returning values rather than output parameters Google

∗ Do not declare functions with an excessive number of parameters. Use a


wrapper structure instead Hic, Core42/80
Functions - Style 3/3

• Prefer enum to bool on function parameters

• All parameters should be aligned if they do not fit in a single line (especially in the
declaration) Google
void f(int a,
const int* b);

• Parameter names should be the same for declaration and definition Clang-Tidy

• Do not use inline when declaring a function (only in the definition) LLVM

• Do not separate declaration and definition for template and inline functions
Google
43/80
Structs and Classes
Structs and Classes 1/3

∗ Use a struct only for passive objects that carry data; everything else is a
class Google

※ Objects are fully initialized by constructor call Google, WebKit, Core

∗ Prefer in-class initializers to member initializers Core

∗ Initialize member variables in the order of member declaration Core, Hic

• Use delegating constructors to represent common actions for all constructors of a


class Core
44/80
Structs and Classes 2/3

∗ Do not define implicit conversions. Use the explicit keyword for conversion
operators and constructors Google, Core

∗ Prefer = default constructors over user-defined / implicit default


constructors Mozilla, Chromium, Core, Hic

∗ Use = delete for mark deleted functions Core, Hic

• Mark destructor and move constructor noexcept Core

45/80
Structs and Classes 3/3

• Use braced initializer lists for aggregate types A{1, 2} LLVM, Google

• Do not use braced initializer lists {} for constructors (at least for containers, e.g.
std::vector ). It can be confused with std::initializer list LLVM

• Prefer braced initializer lists {} for constructors to clearly distinguish from


function calls and avoid implicit narrowing conversion

46/80
Inheritance 1/2

※ Avoid virtual method calls in constructors Google, Core, Cert

※ Default arguments are allowed only on non-virtual functions


Google, Core, Hic

∗ A class with a virtual function should have a virtual or protected destructor


(e.g. interfaces and abstract classes) Core

• Does not use virtual with final/override (implicit)

see A hole in Clang’s -Wsuggest-override 47/80


Inheritance 2/2

∗ Multiple inheritance and virtual inheritance are discouraged


Google, Chromium

∗ Prefer composition over inheritance Google

∗ A polymorphic class should suppress copying Core

48/80
Structs and Classes - Style 1/3

※ Declare class data members in special way*. Examples:


- Trailing underscore (e.g. member var ) Google, µOS, Chromium
- Leading underscore (e.g. member var ) .NET
- Public members (e.g. m member var ) WebKit
Personal Comment: Prefer member var as I read left-to-right and is less invasive

• Class inheritance declarations order:


public , protected , private Google, µOS

• First data members, then function members

• If possible, avoid this-> keyword

* It helps to keep track of class variables and local function variables


49/80
* The first character is helpful in filtering through the list of available variables
Structs and Classes - Style 2/3
struct A { // passive data structure
int x;
float y;
};

class B {
public:
B();
void public_function();

protected:
int _a; // in general, it is not public in derived classes
void _protected_function(); // "protected_function()" is not wrong
// it may be public in derived classes
private:
int _x;
float _y;

void _private_function();
50/80
};
Structs and Classes - Style 3/3

• In the constructor, each member should be indented on a separate line, e.g.


WebKit, Mozilla
A::A(int x1, int y1, int z1) :
x{x1},
y{y1},
z{z1} {

51/80
Control Flow
Control Flow 1/6

※ Avoid redundant control flow (see next slide)


- Do not use else after a return / break
LLVM, Mozilla, Chromium, WebKit
- Avoid return true/return false pattern
- Merge multiple conditional statements

∗ Prefer switch to multiple if -statement Core

∗ Avoid goto µOS, Core

• Avoid do-while loop Core

• Do not use default labels in fully covered switches over enumerations LLVM
52/80
Control Flow - if/else 2/6

if (condition) { // wrong!!
< code1 >
return;
}
else // <-- redundant
< code2 >
//---------------------------
if (condition) { // Corret
< code1 >
return;
}
< code2 >

if (condition) // wrong!!
return true;
else
return false;
//-------------------------
return condition; // Corret 53/80
Control Flow - Loops 3/6

• Use early exits ( continue , break , return ) to simplify the code LLVM
for (<condition1>) { // wrong!!
if (<condition2>)
...
}
//-----------------------------
for (<condition1>) { // Correct
if (!<condition2>)
continue;
...
}

• Turn predicate loops into predicate functions LLVM


bool var = ...;
for (<loop_condition1>) { // should be an external
if (<condition2>) { // function
var = ...
break;
54/80
}
Control Flow - Comparison 4/6

※ Tests for null/non-null , and zero/non-zero should all be done with


equality comparisons Core, WebKit
(opposite) Mozilla
if (!ptr) // wrong!! if (ptr == nullptr) // correct
return; return;
if (!count) // wrong!! if (count == 0) // correct
return; return;

※ Prefer (ptr == nullptr) and x > 0 over (nullptr == ptr) and 0 < x
Chromium

• Do not compare to true/false , e.g. if (x == true)


55/80
Control Flow 5/6

※ Do not mix signed and unsigned types Hic

∗ Prefer signed integer for loop indices (better 64-bit) Core

• Prefer empty() method over size() to check if a container has no items


Mozilla

• Ensure that all statements are reachable Hic

∗ Avoid RTTI (dynamic cast) or exceptions if possible


LLVM, Google, Mozilla
56/80
Control Flow - Style 6/6

※ The if and else keywords belong on separate lines


if (c1) <statement1>; else <statement2> // wrong!!

Google, WebKit
∗ Multi-lines statements and complex conditions require curly braces Google
if (c1 && ... &&
c2 && ...) { // correct
<statement>
}

• Curly braces are not required for single-line statements (but allowed)
( for, while, if ) Google, WebKit
if (c1) { // not mandatory
<statement>
} 57/80
Modern C++
Features
Modern C++ Features 1/4

Use modern C++ features wherever possible

∗ static cast reinterpret cast instead of old style cast (type)


Google, µOS, Hic

∗ Do not define implicit conversions. Use the explicit keyword for conversion
operators and constructors Google, µOS

58/80
Modern C++ Features - C++11/14/17 2/4

※ Use constexpr instead of macro Google, WebKit

※ Use using instead typedef

※ Prefer enum class instead of plain enum Unreal, µOS

※ static assert compile-time assertion Unreal, Hic

※ lambda expression Unreal

※ move semantic Unreal

※ nullptr instead of 0 or NULL


LLVM, Google, Unreal, WebKit, Mozilla, Hic, µOS59/80
Modern C++ Features - C++11/14/17 3/4

※ Use range-based for loops whatever possible


LLVM, WebKit, Unreal, Core

※ 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)

∗ Use [[deprecated]] / [[noreturn]] / [[nodiscard]] to indicate


deprecated functions / that do not return / result should not be discarded

• Avoid throw() expression. Use noexpect instead Hic


60/80
Modern C++ Features for Classes 4/4

※ Always use override/final function member keyword


WebKit, Mozilla, Unreal, Chromium, Hic

∗ Use braced direct-list-initialization or copy-initialization 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 (best option)
};

∗ Use = default constructors

∗ Use = delete to mark deleted functions

• Prefer uniform initialization when it cannot be confused with


std::initializer list Chromium61/80
Maintainability
Maintainability 1/3

※ Avoid complicated template programming Google

∗ Write self-documenting code


e.g. (x + y - 1) / y → ceil div(x, y) Unreal

∗ Use symbolic names instead of literal values in code Hic


double area1 = 3.14 * radius * radius; // wrong!!

constexpr auto Pi = 3.14; // correct


double area2 = Pi * radius * radius;

62/80
Maintainability 2/3

※ Do not use reinterpret cast or union for type punning Core, Hic

※ Enforce const-correctness Unreal

• but don’t const all the things


• Pass by- const value: almost useless (copy), ABI break
• const return: useless (copy)
• const data member: disable assignment and copy constructor
• const local variables: verbose, rarely effective

※ Do not overload operators with special semantics && , ˆ Hic

※ Use assert to document preconditions and assumptions LLVM


63/80
Don’t const all the things
Maintainability 3/3

∗ Address compiler warnings. Compiler warning messages mean something is


wrong Unreal

∗ Ensure ISO C++ compliant code and avoid non-standard extension,


deprecated features, or asm declarations, e.g. register , attribute Hic

∗ Prefer sizeof(variable/value) instead of sizeof(type) Google

∗ Prefer core-language features over library facilities, e.g. char vs. std::byte

64/80
Prefer core-language features over library facilities
Naming
Naming Conventions for Variables 1/2

※ Use full 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

∗ 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 scope.

65/80
Naming Conventions for Variables 2/2

※ Do not use reserved names Cert


- double underscore followed by any character var
- single underscore followed by uppercase VAR

• Use common loop variable names


- i, j, k, l used in order
- it for iterators

66/80
Naming Conventions for Functions

∗ Should be descriptive verb (as they represent actions) WebKit

∗ Functions that return boolean values should start with boolean verbs, like
is, has, should, does µOS

• Use set prefix for modifier methods WebKit

• Do not use get for observer methods ( const ) without parameters, e.g.
size() WebKit

67/80
Style Conventions

Camel style Uppercase first word letter (sometimes called Pascal style or Capital case)
(less readable, shorter names)
CamelStyle

Snake style Lower case words separated by single underscore (good readability, longer
names)
snake_style

Macro style Upper case words separated by single underscore (sometimes called
Screaming style) (best readability, longer names)
MACRO_STYLE

68/80
Entity Names 1/2

Variable Variable names should be nouns


• Camel style e.g. MyVar LLVM, Unreal
• Snake style e.g. my var Google, Std, µOS

Constant • Camel style + k prefix,


e.g. kConstantVar Google, Mozilla

• Macro style e.g. CONSTANT VAR WebKit, OpenStack

Enum • Camel style + k


e.g. enum MyEnum { kEnumVar1, kEnumVar2 } Google
• Camel style
e.g. enum MyEnum { EnumVar1, EnumVar2 } LLVM, WebKit

69/80
Entity Names 2/2

Namespace • Snake style, e.g. my namespace Google, LLVM, Std


• Camel style, e.g. MyNamespace WebKit

Typename Should be nouns


• Camel style (including classes, structs, enums, typedefs, etc.)
e.g. HelloWorldClass LLVM, Google, WebKit
• Snake style µOS (class), Std

Macro Macro style, e.g. MY MACRO Google, Std, LLVM

File • Snake style (my file) Google


• Camel style (MyFile), could lead Windows/Linux conflicts LLVM
70/80
Function Names

• Lowercase Camel style, e.g. myFunc() LLVM

• Uppercase Camel style for standard functions


e.g. MyFunc() Google, Mozilla, Unreal

• Snake style for cheap functions, e.g. my func() Google, Std

Personal Comment: Macro style needs to be used only for macros to avoid subtle bugs. I adopt
snake style for almost everything as 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 as they are very relevant in my work and I need to identify what is
evaluated at compile-time easily

71/80
Readability and
Formatting
Basics

※ Write all code in English, comments included

※ Limit line length (width) to be at most 80 characters long (or 100, or 120) →
help code view on a terminal LLVM, Google, Mozilla, µOS
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 small line length is a good compromise for everyone.

∗ Do not write excessive long file

72/80
• Is the 80 character limit still relevant in times of widescreen monitors?
Spacing 1/2

※ Use always the same indentation style


- tab → 2 spaces Google, Mozilla, Hic, µOS
- tab → 4 spaces LLVM, Webkit, Hic, µOS
- (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

※ Separate commands, operators, etc., by a space LLVM, Google, WebKit


if(a*b<10&&c) // wrong!!
if (a * c < 10 && c) // correct

73/80
Spacing 2/2

∗ Prefer consecutive alignment


int var1 = ...
long long int longvar2 = ...

• Minimize the number of empty rows

• Do not use more than one empty line Google

What is your threshold for a long source file? 74/80


Formatting 1/2

∗ Use always the same style for braces


• Same line, aka Kernigham & Ritchie WebKit (func. only), Mozilla
• Its own line, aka Allman Unreal, WebKit (function)
Mozilla (class)
int main() { int main()
code {
} code
}

Personal Comment: C++ is a very verbose language. ”Same line” convention helps to keep the
code more compact, improving the readability

75/80
Formatting 2/2

• 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, Mozilla, Chromium, Unreal
• char *c;
• char * c;

• The same concept applies to const


• const int* West notation
• int const* East notation

76/80
Other Issues

∗ Use the same line ending (e.g. '\n' ) for all files Mozilla, Chromium

∗ Do not use UTF characters* for portability, prefer ASCII

∗ If UTF is needed, prefer UTF-8 encoding for portability Chromium

• Declare each identifier on a separate line in a separate declaration Hic, Misra

• Never put trailing white space or tabs at the end of a line Google, Mozilla

• Only one space between statement and comment WebKit

• Close files with a blank line Mozilla, Unreal

77/80
* Trojan Source attack for introducing invisible vulnerabilities
Code
Documentation
Code Documentation 1/3

∗ Any file start with a license LLVM, Unreal

∗ 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

• Document each entity (functions, classes, namespaces, definitions, etc.) and only
in the declarations, e.g. header files

78/80
Code Documentation 2/3

• The first sentence (beginning with @brief ) is used as an abstract

• Document the input/output parameters @param[in] , @param[out] ,


@param[in,out] , return value @return , and template paramenters @tparam

• Document ranges, impossible values, status/return values meaning Unreal

• Use always the same style of comment

• Use anchors for indicating special issues: TODO , FIXME , BUG , etc.
WebKit, Chromium
79/80
Code Documentation 3/3

• Be aware of the comment style, e.g.


- Multiple lines
/**
* comment1
* comment2
*/
- single line
/// comment

• Prefer // comment instead of /* */ → allow string-search tools like grep to


identify valid code lines Hic, µOS

• µOS++ Doxygen style guide link


• Teaching the art of great documentation, by Google 80/80

You might also like