Coding Standards¶
See also
This page describes the C++ coding standards used in MAREngine. If you are going to contribute to MAREngine, please read this.
Naming conventions¶
How to choose name?¶
// namespaces can be made up of one word, only lower case letters
namespace example {
// all variables are starting from lower letter, any other word is starting from capital letter
float someVariable;
float someLongNameForVariable;
// all functions are starting from lower letter, any other word is starting from capital letter
void someFunction();
void someLongNameForMethod();
// all classes are starting from capital letter, any other word is starting from capital letter
class SomeClass;
class SomeOtherClass;
}
// examples, that I don't use and are considered as BAD
namespace BadExample { // change name to "example" or "bad", find any other namespace name
namespace Bad { // change to "bad"
class badClass; // change to "BadClass"
}
void Some_Bad_Function(); // change to someBadFunction();
void other_bad_Function(); // change to otherBadFunction();
int32_t __someVariable; // change to someVariable
float other_Example; // change to otherExample
}
How to name local / static / global variables?¶
int32_t localVariable; // for local variables we don't need any prefix
int32_t s_staticVariable; // for static variables add s_ prefix
int32_t g_globalVariable; // for global variables add g_ prefix
How to name variables in class?¶
float m_member; // private member, add m_ prefix
float s_member; // static member, add s_ prefix
float p_member; // protected member, add p_ prefix
float member; // public member, we don't need any prefix
Functions-Standards¶
Follow Single-Responsibility-Principle¶
Define small functions inline¶
Small functions are 3-5 lines long.
Lambdas¶
Avoid [&] or [=]¶
Default capture-modes can catch more than you can expect! Capture variables explicitly.
void SomeClass::foo() {
m_member = 0; // class member
int32_t local = 100;
auto bad_lambda = [=]{ /* do some stuff */ };
auto bad_lambda2 = [&]{ /* do some stuff */ };
auto good_lambda = [&memberData = m_member, local]() {
// do some stuff
};
auto good_lambda2 = [this]() {
// do some stuff
};
// do something
}
Consider capturing as const reference¶
void foo() {
auto someLargObject;
auto good = [LargeConstRef = std::cref(someLargObject)]() {
LargeConstRef.constAction();
};
auto goodCpp17 = [&LargeConstRef = std::as_const(someLargObject)]() { // only with C++17
LargeConstRef.constAction();
};
}
OOP¶
How classes should look like¶
friend declarations
private nested types
public nested types
constructors
destructors
public member functions
public member variables
protected member functions
protected member variables
private member functions
private member variables
class SomeClass {
friend class SomeFriendClass;
typedef int32_t MyInt;
public:
typedef std::vector<std::pair<int32_t, float>> PairVector;
SomeClass();
virtual ~SomeClass();
void public_method();
int32_t member;
protected:
void protected_method();
int32_t p_member;
private:
void private_method();
int32_t m_member;
};
Prefer in-class members initialization¶
class SomeClass {
public:
SomeClass() : // old-style constructor initialization
a(0),
b(0.0),
{}
private:
int32_t a;
double b;
};
It is better to it this way:
class SomeClass {
public:
SomeClass() = default;
private:
int32_t a{ 0 };
double b{ 0.0 };
};
Do not use virtual destructor¶
Remember that move construction and move assignment are disabled if you use virtual destructor! Use it wisely.
Namespaces¶
Increase readability with nested namespaces¶
// This is considered as bad
namespace first {
namespace second {
class SomeClass;
}
}
// This one definitely increase readability
namespace first::second {
class SomeClass;
}
Header Files¶
Forward declarations¶
Prefer forward declaration in .h file, include in cpp file if possible. This can speed up compilation time.
// MyClass.h
namespace example {
class SomeOtherClass;
class MyClass {
void foo(SomeOtherClass* soc);
};
}
// MyClass.cpp
#include "MyClass.h"
#include "SomeOtherClass.h"
namespace example {
void MyClass::foo(SomeOtherClass* soc) {
// do stuff
}
}
Memory Management¶
Initialize pointers with nullptr¶
Do not use NULL or 0 to initialize pointers!
Never use memcpy or memset¶
Always use copy constructors and assignment operators to copy from one object to another. Use std::copy() instead of memcpy(). Alawys use std::fill() or std::fill_n() to assign a specified value to elements of sequence, never use memset().