Rather than try to justify every decision made, this document attempts to be as at-a-glance as possible. Examples provided where necessary to illustrate best practices.
Note that this style guide is, for the most part, not very strict, and there are exceptions to every rule. However, this guide does serve to illustrate the preferred style for the entire codebase.
CamelCaseFirstUpperlowerCamelCase.h, lowerCamelCase.cxx
lower_snake_case_without_prefixlower_snake_case_without_prefix_lower_snake_case_with_initial_scoreSE_enum_value (for an enum type named SomeEnum)ENUM_VALUEAlways use two spaces to indent. Tabs should never appear in a C++ file.
Access modifiers (public/private/protected/PUBLISHED) are never
indented relative to the class they are in, and do not affect the indentation
of the surrounding lines.
Always put one space after a control keyword, before the condition's parentheses. Don't pad the inside of parentheses with spaces unless there are several nested parenthetical expressions and the extra spaces contribute substantially to readability.
if (x == y) {
Don't place a space after a function name (declarations, definitions, or calls).
void function_name();
...
function_name();
Always place a space after each comma in an arguments list.
function_call(x, y, z);
Always pad binary operators with a space on either side.
a || b
Never end a line with trailing whitespace.
The recipe for a function definition is:
For example:
/**
* String documenting the function, in JavaDoc style.
*/
void ClassName::
function_name(int x, int y) const {
...
}
/**
* ...
*/
...
If the function is a constructor with an initializer list, the : goes on the
same line as the constructor name, and the initializers are listed one per
line, indented by two spaces.
ClassName::
ClassName() :
_a("a"),
_b("b"),
_c("c")
{
}
Empty function bodies in a .cxx/.I file still contain a single line break (i.e.
to put } on its own line). In a .h file, an empty function can be given as
{}
Always put an opening { on the same line as the statement that calls for the
brace. There is exactly one exception to this: constructors with initializer
lists.
SomeClass::
SomeClass() :
_one(1),
_two(2)
{
if (_one < _two) {
...
}
}
Comments should be properly-formatted English, with proper capitalization and punctuation rules. There are two spaces between sentences.
Note that // is preferred over /* except in some special circumstances.
Except for commented-out lines of code, there should be a space between the
first word and the //.
// The following line is commented out.
//if (value == 0) {
Lines should be limited to 80 columns. This is not a hard limit, and lines should not be wrapped if doing so hurts readability, except comments, which should always be wrapped.
Continuation lines shall be aligned to the same column as appropriate, or indented two spaces otherwise:
if ((a &&
b) ||
c) {
...
}
When choosing where to break a line, these are the preferred places, from best to worst:
<<, before a <<. (Avoid ending a line with <<)"This is a " / "continued string literal.")= in an assignment operator.( in a function call.If none of these rules can apply cleanly, it is okay to have lines extend past the 80-column boundary.
Avoid the temptation to align multiple assignments in consecutive lines of code. While it may look neater, it decreases the maintainability of the code.
Asterisks and ampersands indicating a pointer or reference type should always be aligned against the name, and not the type:
Type *x, &y;
Try to group logically-similar lines, separating them with a single blank line.
Panda3D is a C++14 project. The use of the following modern language features is greatly encouraged:
nullptr over NULLstd::move and move semanticsUsing auto can be okay, such as when storing an iterator, but consider
creating a typedef for the container type instead.
Avoid using std::function in cases where a lambda can be accepted directly
(using a template function), since it has extra overhead over lambdas.
C++17 features should be avoided for now.