-
Notifications
You must be signed in to change notification settings - Fork 35
The (Tentative WIP) XPTools CPP Style Guide
XPTools is (as of writing) at least 11 years old, and has been primarily written by one author (bsupnik.) As such there are multiple coding styles used throughout the code base. Going forward we want to develop a uniform style guide to follow and adopt a static code analysis formatter to enforce it. Until then, here is a tentative style guide for new code. Be locally consistent above using new rules. (Note: Some of the content of this guide is take from Google's C++ style guide, however there are changes to be aware of!)
Under the "say what you mean principle", use the bool
datatype for values that will be true or false and int
for numeric values.
Given WED's lack of code documentation, returning a boolean over a 0 or 1 is more clear. It also discourages the use of returning hard coded and brittle (and likely undocumented) error codes instead of using an enum or other safer constructs.
Going forward, always use C++ string
s instead of C-Style const char*
strings. Update the existing APIs as is convenient.
The only exception is for creating debug labels. For example:
void make_a_widget_for_fred(int foo, xflt bar, const char * debug_label);
Prefer C++ style comments (//
) over C style comments (/**/
) as C style comments don't nest. Use #if 0 ... #endif
for disabling large chunks of code.
Place the comments describing the purpose of the variable or function above the deceleration of it. This supports most IDE's ability to take this line and show it in tool tips in addition to saving horizontal space.
//Pointer to the original WED_TaxiRoute in WED's data model
WED_TaxiRoute* taxiroute_ptr;
Do not use brace-less if
's, else
's, for
's, while
's unless it makes the code exceptionally beautiful and elegant. This is a bug prevention decision.
Good
if(x == 1)
{
DoThing();
}
Bad
if(x == 1)
DoThing();
Single line statements such as
if(x == 1) Func();
are absolutely prohibited due to the difficulty of placing a breakpoint on the expression following the selection or iteration statement.
Return type on the same line as function name, parameters on the same line if they fit. Wrap parameter lists which do not fit on a single line.
Functions look like this:
ReturnType ClassName::FunctionName(Type par_name1, Type par_name2)
{
DoSomething();
...
}
If you have too much text to fit on one line:
ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
Type par_name3)
{
DoSomething();
...
}
or if you cannot fit even the first parameter:
ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
Type par_name1, // 1 indent
Type par_name2,
Type par_name3)
{
DoSomething(); // 1 indent
...
}
Some points to note:
- Choose good parameter names.
- Parameter names may never be omitted.
- If you cannot fit the return type and the function name on a single line, break between them.
- If you break after the return type of a function declaration or definition, do not indent.
- The open parenthesis is always on the same line as the function name.
- There is never a space between the function name and the open parenthesis.
- If first parameter's type is on the first line, there is no space between the open parenthesis and it.
- The open curly brace is always on the next line, with the exception of empty implementations of methods.
- The close curly brace is always on the last line by itself, with the exception of empty implementations of methods.
- All parameters should be aligned if possible.
- Wrapped parameters have a 1 indent.
Rules for empty implementations of methods:
- There should be a space between the close parenthesis and the open curly brace.
- Open and closed curly braces appear on the same line with 0 or 1 spaces in between.
virtual void DragScroll (int x, int y) { }
Use Unix line endings only.
Aim for 80 characters, 100 is okay too, stop at 120.
All identifiers must be in ASCII. Hard coded strings and characters featuring Unicode characters in code should be written with the C++ Unicode literal escape sequence and given a comment with the actual Unicode character and a description of it.
Good
//â, latin small letter a with circumflex
string facade_type = "ch\u00E2teauesque";
Bad
//â, latin small letter a with circumflex
string façade_type = "châteauesque";
We can afford Unicode in comments to be trashed by an encoding change, not in source code.
Use tabs to indent, spaces inside the rest of the line, even for spans of greater than 4 spaces.
Header guards should be in the form of FILE_NAME_IN_ALL_CAPS_H. For example GUI_PopupButton.h
's guard is GUI_POPUPBUTTON_H
. All caps, no extra spaces inserted between words. We do not use #pragma once
.
Put the public interface portion first, followed by protected members, and finally private members. Within each order, group by related purpose and order alphabetically. Use newlines and comments between sections to mark them. Inherited functions should be especially grouped together and marked, with a comment above saying which class they originate from. Omit empty sections.
Default parameters should go in the declaration instead of in the definition. This better communicates if there is or is not defaults set and the expected behavior of the method without having to look at the definition.