CamelCase: class names template parameters, file names, and directory names.
snake_case: function, variable, metafunction and metavariable names.
SCREAMING_SNAKE_CASE: macros.
Functions or classes only used internally in a library should be in a namespace named LibraryOrFile_detail. For example, databox_detail, Tensor_detail or ConstantExpressions_detail.
Name unused function parameters /*parameter_name*/ or /*meta*/ for TMP cases
Type aliases that wrap type traits have a trailing _t following the STL
Use C-style Doxygen comments (/*! ... */) when using multi-line math, otherwise C-style and C++ style comments are accepted.
Use the align environment instead of eqnarray. See the texfaq for an explanation as to why.
Multi-line equations must have a blank Doxygen line before and after the equation.
When addressing requests on a PR, the commit message must start with fixup followed by a descriptive message.
All python code must comply with the black formatting specified by the pyproject.toml file.
Imports in Python code must be sorted to comply to the isort formatting specified in the pyproject.toml file.
Code Quality Items:
All code passes Clang and CppCheck static analyzers. For help with these tools see here.
Almost always auto, except with expression templates, i.e. DataVector
All loops and if statements use braces.
Order of declaration in classes is public before private and member functions before data. See Google.
Prefer return by value over pass-by-mutable-reference except when mutable reference provides superior performance (in practice if you need a mutable reference use const gsl::not_null<Type*> instead of Type&). The mutable references must be the first arguments passed to the function.
All commits for performance changes provide quantitative evidence and the tests used to obtain said evidence.
Never include <iostream>, use Parallel::printf inside Parallel/Printf/Printf.hpp instead, which is safe to use in parallel.
When using charm++ nodelocks include <converse.h> instead of <lrtslock.h>.
Virtual functions are explicitly overridden using the override keyword.
#pragma once is to be used for header guards
Prefer range-based for loops
Use size_t for positive integers rather than int, specifically when looping over containers. This is in compliance with what the STL uses.
Error messages should be helpful. An example of a bad error message is "Size
mismatch". Instead this message could read "The number of grid points in the
matrix 'F' is not the same as the number of grid points in the determinant.", along with the runtime values of the mentioned quantities if applicable.
Mark immutable objects as const
Make classes serializable by writing a pup function
If a class stores an object passed into a constructor the object should be taken by-value and std::moved into the member variable.
Definitions of function and class templates should be in .cpp files with explicit instantiations whenever possible. The macro GENERATE_EXPLICIT_INSTANTIATIONS is useful for generating many explicit instantiations.
Functions should not be marked noexcept unless it is part of the signature of an overriden function (e.g. the what() function of an exception derived from std::exception).
Variable names in macros must avoid name collisions, e.g. inside the PARSE_ERROR macro you would write double variable_name_avoid_name_collisions_PARSE_ERROR = 0.0;
Explicitly specify doubles, e.g. sqrt(2.) or sqrt(2.0) instead of sqrt(2).
When the index of a Tensor is known at compile time, use get<a, b>(tensor) instead of the member get function.
All necessary header files must be included. In header files, prefer forward declarations if class definitions aren't necessary.
Explicitly make numbers floating point, e.g. 2. or 2.0 over 2.
Avoid mutable member variables. If you think you really need these, discuss with at least 2 core developers. In a parallel environment mutable variables lead to race conditions since multiple threads can mutate a single object by calling a const member function.