This page summarizes the coding conventions used for FEAT.
- Note
- This page is work-in-progress and therefore the information is incomplete.
Contents
1. General Conventions
- FEAT 3 is written in the C++17 standard, namely: ISO/IEC 14882:2017.
- All code and documentation is to be written in American English.
- It is strongly recommended that lines should not exceed 120 characters.
- All header and source files shall begin with the copyright disclaimer:
- All header files shall begin with a
#pragma once directive directly after the initial copyright disclaimer and optional comment blocks.
- Includes of FEAT header files are to be given relative to the FEAT root directory.
- Included header file paths are to be enclosed in angle brackets < >.
- One line shall not contain more than one statement.
- Reference (&) and Pointer (*) specifiers are to be positioned directly after the data type and not in front of the variable name.
- It is recommended that only one pointer or reference is be defined per statement.
- The keyword for the Null-Pointer is the C++11
nullptr and not (void)*0, 0 or NULL.
- The usage of the
goto statement is not allowed.
- Assertions shall be implemented by using one of the ASSERT, ASSERTM, XASSERT and XASSERTM macros.
- Program abortion shall be implemented by using the XABORTM macro.
- The use of platform-dependent code switches – independent of whether at preprocessortime, compiletime or runtime – is to be kept to a minimum and each platform switch must be documented by using the (custom)
\platformswitch doxygen command.
- The use of compiler hacks is to be kept to a minimum and each compiler hack must be documented by using the (custom)
\compilerhack doxygen command.
2. Naming Conventions
The purpose of this section is to define three naming conventions, which are referenced frequently throughout the rest of this page.
The following list prescribes what type of naming convention is to be used for each language construct.
- preprocessor macros: UPPER_SNAKE_CASE
- namespaces: CamelCase
- class/struct/type names: CamelCase
- template type parameters: CamelCase postfixed by a single underscore
- template value parameters: lower_snake_case postfixed by a single underscore
- enumeration names: CamelCase
- enumeration values: lower_snake_case
- variable names: lower_snake_case
- function names: lower_snake_case
- function parameters: lower_snake_case
- public class member variable names: lower_snake_case
- public class member function names: lower_snake_case
- private/protected class member variable names: lower_snake_case prefixed by a single underscore
- private/protected class member function names: lower_snake_case prefixed by a single underscore
- everything else not explicitly mentioned above: lower_snake_case
2.1 Camel-Case
Character Set
- latin letters: 'a' - 'z', 'A' - 'Z'
- decimal digits: '0' - '9'
Definition
A compound of words is written in Camel-Case by capitalizing the first letter of each word and joining all words without spaces. Unless stated otherwise, the leading character must be an upper-case latin letter.
Examples
Convention
VectorNorm
MySuperClass
CPlusPlus2003
- See also
- http://en.wikipedia.org/wiki/CamelCase
2.2 Lower Snake-Case
Character Set
- lower-case latin letters: 'a' - 'z'
- decimal digits: '0' - '9'
- underscore: '_'
Definition
A compound of words is written in lower Snake-Case by joining all words, separating them by underscores. Unless stated otherwise, the leading character must be a lower-case latin letter.
Examples
mathematics
foo_bar
my_object_pointer
- See also
- https://en.wikipedia.org/wiki/Snake_case
2.3 Upper Snake-Case
Character Set
- upper-case latin letters: 'A' - 'Z'
- decimal digits: '0' - '9'
- underscore: '_'
Definition
A compound of words is written in upper Snake-Case by capitalizing each word and joining all words, separating them by underscores. Unless stated otherwise, the leading character must be an upper-case latin letter.
Examples
FOOBAR
MAKE_MONEY
PRINT_TO_SCREEN
- See also
- https://en.wikipedia.org/wiki/Snake_case
2. Indentation, Spacing and Line Breaks
- Indents are realized using 2 spaces; leading TABs are not allowed. In fact, leading TABs are rejected by our main repository's pre-commit hook.
- Trailing whitespaces are not allowed and are rejected by our main repository's pre-commit hook.
- Each source and header file shall contain a single empty line at the end of the file. Multiple empty lines are rejected by our main repository's pre-commit hook.
- If line breaks within a statement are necessary, each line of the statement except for the first one shall have one additional indent.
- It is permitted to use additional spaces pretty much anywhere inside a statement if the author thinks that this improves the readability of the corresponding code section.
- It is permitted to use empty lines if the author thinks that this improves the readability of the corresponding code section. However, multiple consecutive empty lines are to be avoided.
- The code inside a pair of curly braces { } is to be indented.
- Exception: The
private, protected and public keywords in a class or struct definition as well as the case and default keywords in a switch statement are not to be indented.
- Each opening curly brace { shall stand alone in a separate line on the same indent as the statement that preceedes the curly brace. The commonly used C-style convention that the opening brace { is appended to the statement opening the scope shall be avoided.
- Each closing curly brace } shall stand alone in a separate line on the same indent as the opening curly brace { that forms a pair with the closing curly brace.
- If a closing curly brace } denotes the end of a class/struct/union definiton, then the mandatory semicolon shall be placed directly after the curly brace in the same line.
- It shall not happen that two closing curly braces } in two consecutive lines differ by more or less than a single indent. This is not a rule by itself, but rather a corollary of the previous indentation rules regarding curly braces.
if(k == 0)
{
return 0;
}
else
{
while(k > 2)
{
k = (k+3) >> 2;
}
}
- If a function or template parameter list is to be split across several lines, then all lines except for the first one shall to be indented by a single indent.
template<
typename DataType_,
typename IndexType_>
void foobar1(
DataType_* alpha,
DataType_* beta,
IndexType_ length)
{
...
}
template<typename DataType_, typename IndexType_>
void foobar2(DataType_* alpha, DataType_* beta, IndexType_ length)
{
...
}
- Binary operators shall be enclosed by single spaces; the spaces around the multiplication asterisks and division slashes may be omitted.
foo = (3*bar + qux/7) >> (k & 3);
- Each comma , colon : and semicolon ; is to be followed by a space or a line break.
- The
case and default keywords in a switch block are to be placed on the same indent as the switch keyword, but all statements in a case or default block are to be indented by a single indent.
- All
case blocks in a switch statement shall either end with a break or a C++17 [[fallthrough]] statement.
- It is recommended to insert a single empty line before each
case and default block in a switch statement, except for the first block in that statement. switch(qux)
{
case 0:
bar = 17;
[[fallthrough]];
case 1:
{
qux += 2;
}
break;
default:
bar = 0;
break;
}
3. Preprocessor Directives and Macros
- In general, the use of preprocessor macros and directives – especially dirty preprocessor hacks – shall be kept to a minimum.
- All preprocessor directives, which are supported by FEAT and which are either defined by the build system or the user, must be documented in the Preprocessor Macros page.
- Preprocessor directives must always stand in the first column of each line, i.e. preprocessor directives are never indented.
- The use of preprocessor directives, including preprocessor if-sections, has no impact on code indendation.
- It it recommended that each
#else and #endif directive is appropriately commented to indicate to which #if block it belongs to void foobar()
{
#ifdef FEAT_HAVE_MPI
int my_rank = Dist::Comm::world().rank();
if(my_rank == 0)
{
std::cout << "Hello World from master!" << std::endl;
}
#ifdef DEBUG
else
{
std::cout << "Hello World from slave " << my_rank << " in debug mode!" << std::endl;
}
#endif
#else
std::cout << "Hello Serial World!" << std::endl;
#endif
}
4. Functions
5. Classes, Structs and Unions
- Class, struct and union names are to be written in CamelCase.
- Multiple inheritance shall be avoided.
- Member variables and member functions are to be written in lower_snake_case.
- Private or protected member variable and member function names are to be prefixed by a single underscore.
- Nested type declarations (classes, structs, unions, enums, typedefs) are also to be written in CamelCase. Protected and private nested type declarations are not to be prefixed by underscores.
- User-defined constructors shall be declared
explicit unless implicit conversion is explicitly desired.
- It is encouraged that the contents of a class or struct definition are structured in the following order:
- nested type declarations
- member variables
- member functions
- Member variables and nested type declarations shall not be scattered across the class/struct definition body between member functions but instead shall be grouped into coherent blocks even if the author chooses to disobey the previous rule.
- The
private, protected and public keywords in a class or struct are to be placed on the same indent as the class/struct keyword: class FooBar
{
private:
int _my_value;
protected:
void _reset_value()
{
_my_value = 0;
}
public:
explicit FooBar(int value) :
_my_value(value)
{
}
int get_value() const
{
return _my_value;
}
};
- It is recommended that the final closing curly brace of a class definition is followed by a short comment containing the class name.
6. Templates
7. Namespaces
- The usage of
using namespace at namespace scope is not allowed in header files.
- However,
using namespace is allowed to be used at class or function scope.
8. Miscellaneous
- Enumerations shall be defined as C++11
enum class constructs. The use of the classical C-style non-class enum is not allowed.
- Enumeration names are to be written in CamelCase whereas enumeration values are to be written in lower_snake_case:
enum class PlaceHolder
{
foo_bar = 0,
zumba_dance
};