C++ Style Guide
Pull requests will not be merged until styling issues have been fixed.
Pull requests with bad style are less likely to be accepted.
Formatting
Line Length
Each line of text should be at most 100 characters long.
Indentation
Use only spaces, not tabs. Indent with 4 spaces at a time.
The contents of namespaces are not indented.
Class/struct access specifiers should be indented 2 spaces.
class Foo
{
public:
Foo();
};
Case statements should be at the same indentation as their switch, with indented logic.
switch(day) {
case Monday:
return 1;
case Tuesday:
return 2;
default:
return 0;
}
Braces
Braces for control statements should be attached.
Class and function braces should be on their own line (unless its for an empty block).
Control statements should use consistent braces (ie. if the if
uses braces so should the else
.)
Whitespace
There should be no space between a conditional and its condition (if(foo)
).
There should be a space between a control statement and its brace (switch(val) {
).
There should be no space between template specifiers and their template arguments.
Nested template specifiers should have spaces between right angle-brackets.
Prefer no spaces inside parentheses (while(true)
vs while( true )
).
Newlines
Source files should end with a newline.
Short conditional statements may be written on one line if this enhances readability.
When declaring nested namespaces, put each namespace on its own line.
If statements should be broken before the logical operator.
Naming
Variable Names
Variables should have a descriptive lowercase name, where words are seperated by underscores.
Member variables should start with m_
. Global variables should start with g_
.
Example: field_count
or
class Foo
{
private:
int m_my_number;
};
Function Names
Functions should have a descriptive lowercase name, where words are seperated by underscores.
Class Names
Class names should be in CamelCase
Example: DistributedObject
Typedefs
Typedefs should have a descriptive lower-case name, ending with _t
.
Non-standard/very-complicated typedefs should moonlight with class names.
Example: typedef unsigned int uint32_t
Example: typedef std::unordered_set<const Foo*, CompareFooPtr> FooSet
Header Files
Header Guards
Astron uses #pragma once
as a header guard. All headers should have this line as the first
non-comment line in the file. Guards SHOULD NOT use the #ifndef
and #define
semantics.
Inline Functions
Functions should only be defined inline when they are small (~10 lines or less).
Function Parameter Ordering
Functions parameters should be ordered with inputs preceding outputs.
Names and Order of Includes
Include paths should include the full path from the src/
directory, with the exception of the
header file corresponding to this file (ie. foo.cxx
should use #include "foo.h"
).
Internal includes should use quotations and external includes should use angle brackets.
Include order:
- Header file corresponding to this source file (if exists)
- C system files
- C++ system files
- External headers
- Internal headers (ordered by logical dependency)
Miscellaneous
Function Arguments
Types from stl should be passed by constant reference const ref&
whenever possible.
Local Variables
Initialize local variables as soon as they are declared.
Declare local variables as close to the first use as possible.
Member Variables
Simple member variables should use in-class member initializations.
More complex member variables and variables set by arguments should be initialized in a constructor.
Explicit Constructors
Use the C++ keyword explicit
for constructors with one argument.
If a conversion is intended, it should be clearly marked with comments.
Copy Constructors
Disable copy and assignment operators with = delete;
.
If a copy constructor is necessary, provide both a copy constructor and assignment operator.
Operator Overloading
When implementing comparison operators, provide an implementation for all six of them.
Comparison operators should be declared outside of a class (as non-member functions).
Don't overload other operators -- if you need to, follow normal C++ semantics.
Iterators
Use prefix form (++i
) of the increment and decrement operators with iterators.
Complex iterator types should use the auto
keyword. Never use auto
for anything else.
Integer Types
Of the built-in C++ integer types, only use int
and unsigned int
.
If a variable is always of a specific size, use precise-width integers.
Null Values
Use nullptr
instead of NULL
.