- NO FILE HEADERS
- header guards are expected in .hpp
- MACROS should not be abused. (should only be used for plateforme specific stuff)
-
Naming is important: functions should do what is said on the Tin.
-
No name preceded by an underscore.
-
Class names in PascalCase.
-
Variable & function names in camelCase.
-
Macros, constexpr variables & template parameters in UPPER_CASE.
-
File naming in CamelCase.
Both styles are accepted:
a {
}
a
{
}
However if the first style makes the code hard to read, it may be rejected.
Please use spaces adequatelly:
- after a ','
- around binary operators
- no space for unary operators
Spaces on empty lines are tolerated.
Indenting levels should be 2 spaces wide.
This part may be controversial: Tabs are 8 spaces (Rational: because terminals tend to display them like that). Only indent with tabs if your code remains readable in such an environnment.
The exact indentation does not matter. It is only important that the code is readable.
- Please be nice to miss Cache. (✿◕‿◕✿)
Rational: robustness
- Please adopt strict RAII: no
new
s should be alone. Usestd::unique_ptr
,std::shared_ptr
or something. - Avoid explicit ressource handling. (encapsulate as much as possible)
- Functions which have to be paired, should be maintained as objects.
- Pointers are discouraged.
Exceptions to these rules may be granted to this rule if interacting with a cubbersome API, however then exceptions should remain local.
Rational: speed and robustness
- Templating is encouraged, as well as
constexpr
usage, however careful: we have to handle more compilers than gcc. - Anything that can be
constexpr
should be. Anything that can beconst
should be. - Use of the Standart Template Library over home-made loops is encouraged.
- Avoid useless checks. Code should be verified compile-time, not run-time.
- Virtual inheritence must be justified.
dynamique_cast
and any other form of Run-Time Type Information IS FORBIDDEN.
- classes must be as logically segmented as possible. A classe should't contain to many fields.
- If a groupe of fields is allways used together, they should be seperated in heir own classe.
- If you have a setter, consider using a non const getter instead:
constexpr X &getX();
constexpr X const &getX() const;
- Use struct if all your members are public.
- Use
static_cast
when casting classes.
- Be clear if your object is movable or copiable or none of both.
- Use the default and delete keyword when possible.
- Don't forget to qualify constructors as
constexpr
when possible when using them. - Use the copy-and-swap idiom when appropriate. Use swap in move operator=.
- Operators should be logical,
c = a + b
andc = a; c += b
should have the same result. - Think about operator precedence when overloading.
- If possible, define
@
from@=
(i.e.+
from+=
) to avoid code duplication.
constexpr T &T::operator@=(T const &other);
constexpr T operator@(T const &a, T const &b)
{
return T(a) += b;
}
- Use C-style casts when converting primitive types.
- Use a
static_cast
if a classe is involved, - Other casts are strongly discouraged, except
dynamique_cast
which is forbidden.