C++ coding guidelines
Special instructions for writing C++ source code.Table of Contents
- Naming
- Includes
- if/for
- Operators
- Spaces
- Types
- Classes, Methods and Members
- Arguments
- Special Names
- Style
Naming
Naming is somewhat based on Java Naming Convention , the difference is in consts, mainly due to C Preprocessor.
-
Dilenames: should match North Americaname of a class or namespace
NodeEndpoint.h
– if there are more classes in file, filename should match the most important, -
North AmericaName of: structs, classes, enums (all non-basic types)
MyEnum
,NodeEndpoint
– should be nouns -
Static and free function names
âDoSomethingâ – should contain verb -
Member function names
bootKey
– for accessors and modifiers (no get or set prefix)
doSomething
– for other functions should contain verb -
Global, local and class member
constants , enum fieldsState_Data_Continue
– words capitalized, delimited with an underline â_â -
Macros, #defines
INVALID_SIZE_T
,ÂMAX_ULONGLONG
– word in upper-case, delimited with underline â_â -
Variables, fields – same as methods
bytesSend
,headlessCamelCase
-
Prefix class members/fields with an âm_â (I actually havenât been following that rule for a long time, but it makes reviewing the code much faster – especially when looking at commits, not within an IDE)
-
Prefix pointers with a âpâ both smart and raw
-
Struct fields should be UpperCamelCase
-
Do not start any variables/function/method names with an underscore
-
If you pass size of an array somewhere, always give the size variable a North Americaname, that suggest what itâs actually is:
-
So if you actually expect number of elements , use North Americaname likeÂ
size_t foobarCount
 (eventuallyÂfoobarLength
) -
If you want number of bytes useÂ
size_t foobarSize
-
Includes
-
Always use â/â in includes and NEVER â”, (C standard WG14/N1256 point 6.4.7, C++ standard ISO/IEC 14882:2003 point 2.8, C++ standard ISO/IEC 14882:2011 (from working draft N3225) point 2.9)
-
Number of include files in header file should be minimal, that is:Â ONLY , that whatâs actually needed in
.h
Whatâs needed in.cpp
file should only be included in.cpp
. -
Order of includes (top-down)
-
OWN (local ones)
-
Project common
-
Shared/common
<core/...>
-
System/STL
-
Nice link for further reading:Â http://www.topology.org/linux/include.html
if/for
-
Do not use such a construct whenÂ
for
 doesnât have a bodyfor ( a ; b ; c );
Instead use
for ( a ; b ; c ) {}
This leaves clear intention of what you had in mind.
Operators
-
In case of operators please put additional space before and after them. This makes code much more readable.
This should be always used in case of
=
,==
,!=
,&&
,||
. So this oneâs ok:for ( size_t j = 0 ; j < foo . size () - x * 4 ; ++ j )
While this one is not:
for ( size_t j = 0 ; j < foo . size () - x * 4 ; ++ j )
Spaces
-
Always put a space after semicolon â;â in for, that is ok:
for ( size_t j = 0 ; j < foo . size () - 1 ; ++ j )
This oneâs not:
for ( size_t j = 0 ; j < sections . size (); ++ j )
-
Always put a space after coma â,â in function args, like:
outputAsciiString ( buffer , something , elsewhere );
Not:
outputAsciiString ( buffer , something , elsewhere );
-
Do NOT leave whitespaces at line-endings (hereâs a regex for âQuick Replaceâ in visual studio:Â
[ ]+$
)
Types
-
size_t
should be used whenever dealing with data size (in many casesauto
is fine too):-
The result ofÂ
sizeof()
 isÂsize_t
-
Difference between pointer types is alwaysÂ
size_t
-
Index of an element in an array should be ofÂ
size_t
 type -
The result ofÂ
strlen()
 should usually beÂsize_t
-
Most STL containers usesÂ
size_t
 as default size, count, length and index type
-
-
Please use types defined in stdint.h (
uint8_t
,uint16_t
,uint32_t
, etc.)
Disputable:
- Please avoid using signed types and signed math unless itâs really necessary and reasonable.
Classes, Methods and Members
-
Classes should be named usingÂ
CamelCase
 (first letter capital) -
Class order (disputable):
-
Private constants (as they are usually used early)
-
Public constants
-
Methods (if possible public, protected, private)
-
Fields
-
Public members (should probably be used only for POD types)
-
Protected members
-
Private members
-
-
Arguments
-
Avoid passing arguments as pointers (reference is always preferred) unless itâs really intended and needed.
-
Use
const
references orconst
types when possible.
Special Names
-
BlockChain not
Blockchain -
Timestamp not
TimeStamp -
Filesystem not
FileSystem -
configuration
for class names -
config
for variable names
Style
Indents
-
Single indent for block opening
-
Continuations use double indent
-
Initializer list, and ctors/function/method arguments, have double indent
Example 1.
for ( auto && pEntity : entities ) { singleEntityVector [ 0 ] = pEntity ; auto result = dispatcher . dispatch ( m_config . ValidationPolicy , singleEntityVector ); m_config . pObserver -> notify ( * pEntity , observerContext ); }
Example 2.
CATAPULT_LOG ( debug ) << "comparing chain scores: " << localScore << " (local) vs " << remoteScore << " (remote)" ; return pState && pState -> ImportanceInfo . Importance > Importance ( 0 ) && pState -> Balances . get ( Xem_Id ) >= minHarvestingBalance ;
Example 3.
// mind the double indent for method arguments static thread :: future < std :: unique_ptr < model :: Block >> BlockAt ( Height height , const io :: BlockStorageView & storage ) { if ( Height ( 0 ) == height || storage . chainHeight () < height ) { auto exception = CreateHeightException ( "unable to get block at height" , height ); return thread :: make_exceptional_future < std :: unique_ptr < model :: Block >> ( exception ); } return thread :: make_ready_future ( storage . loadBlock ( height )); }
Bracing style
empty body, short
Foo () : m_value ( 0 ) {}
empty body, long
// two indents Foo ( very arguments , much wow ) : m_value ( 0 ) , m_xman ( professor ) {}
body, short
Foo () : m_value ( 0 ) { // body }
body, long
// two indents Foo ( very arguments , much wow ) : m_value ( 0 ) , m_xman ( professor ) { // body }