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.cppfile 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_tshould be used whenever dealing with data size (in many casesautois 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
constreferences orconsttypes when possible.
Special Names
-
BlockChain not
Blockchain -
Timestamp not
TimeStamp -
Filesystem not
FileSystem -
configurationfor class names -
configfor 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 }