This section covers organization of the source code in files.
Use flat file organization, with all source files located in the same root directory.
All files names must use lower case ASCII letters only, with underscores to separate multiple words if necessary.
Use .cpp
extension for the source file, .hpp
extension for the headers and
.?pp
for the other kinds of source files, e.g. currently .tpp
is used for
template definitions which don't need to be included by all the class clients
and .xpp
is used for the X-Macros.
All text files should use Unix EOL format, i.e. \n
(ASCII LF).
Wrap lines longer than 80 characters.
Exception: Do not wrap copyright lines, containing long list of years.
The indentation unit is 4 spaces, hard TABs must only be used in the makefiles.
Write if(condition)
, without any extra spaces.
Write call_function(arg1, arg2, arg3)
, with a single space after each comma.
Exception: Do not insert space in template instantiations such as
std::pair<T,U>
to keep the type a single syntactic unit.
When a line needs to be wrapped, indent and vertically align the separators.
For the wrapped function calls, indent the opening parentheses and align it with the subsequent commas, e.g.:
call_function
(arg1
,arg2
,arg3
);
For the other expressions, indent and align the separator between the terms:
std::cout
<< "Hello "
<< "world"
<< "!"
<< "\n"
;
The opening brace of compound statements (if
, while
, switch
, ...) must be
on its own line and indented relatively to the statement line itself. The
closing brace must be vertically aligned with the opening brace.
Notice that this means that the compound statement body has the same indentation level as the braces surrounding it.
Example:
if(condition)
{
do_something();
do_something_else();
}
Always use braces for compound statements, even in the situations where the language rules allow omitting them, e.g.
for(;;)
{
wait();
}
Make the definition of the special member functions, i.e. default, copy and
move constructors, copy and move assignment operators and destructor, explicit,
using = default
or = delete
as necessary.
Exception: there is no need to explicitly delete the move constructor/assignment operator if it is already implicitly disabled, e.g. by the presence of a copy constructor/assignment operator.
Define the special member functions inline, directly in the class declaration whenever possible. E.g. for the destructor do always do it except when:
- The destructor is pure virtual and cannot be defined at the point of declaration.
- The class has smart-pointer members of forward-declared types.
In the latter case, use the standard comment explaining why is it done so:
/// Destructor.
///
/// Although it is explicitly defaulted, this destructor cannot be
/// implemented inside the class definition, where a class type that
/// it depends upon is incomplete.