-
Notifications
You must be signed in to change notification settings - Fork 81
Preferred Code Style
Always use spaces, not tabs. 4 spaces indent a block. Continuation can be aligned to the previous line, or with double-indent:
DoSomething(arg1, arg2, arg3,
arg4, arg5, arg6);
DoSomethingElseWithLongFunctionName(
arg1, arg2, arg3,
arg4, arg5, arg6);
New line for opening brace. Visibility specifiers are aligned with the container's braces.
namespace plFoo
{
class plBar
{
public:
int Baz()
{
return 42;
}
};
}
static int foo()
{
return 42;
}
Keep on the same line. Else is attached to the closing brace
if (x < y) {
// stuff
} else {
// Other stuff
}
if (SomeLongCondition(x, y)
&& SomeOtherLongCondition(z, w)) {
// Stuff
} else {
// Other stuff
}
Braces are optional. It is never acceptable to put a one-line block on the same line as the if statement.
if (x < y)
return 5;
else
return 10;
Don't put closing braces on their own line.
void Foo() { }
void plFoo::Bar(int x)
{ }
Cases align with switch statement. Braces are indented (excluding the break
) and used only when necessary. Always include default, even if it is empty.
switch (condition) {
case 1:
// Code for case 1
break;
case 2:
{
int x;
// Code for case 2
}
break;
default:
// Nothing to do
break;
}
Initializer lists are indented on the next line
plMyKlass::plMyKlass()
: plParent(foo), fZeroInitialized(), fNonZeroInitialized(42)
{
// Stuff
}
plMyOtherKlass::plMyOtherKlass(int x)
: MyKlass(), fFirst(), fSecond(42),
fThird(8.1), fFourth("Hello")
{ }
Pointers and references bind to the type. Do not put more than one pointer or reference declaration in the same line. The first const is on the left of the type.
unsigned int x;
const unsigned int x;
const unsigned int* x;
const unsigned int& x;
const unsigned int** x;
const unsigned int* const* x;
char* str1;
char* str2;
char fixedStr3[64];
C 11 allows nested templates to be used without an extra space:
std::vector<std::map<int, char>> x;
Specify parent(s) on same line
class plFoo : public plBar, public plBaz
{
public:
// Contents
};
Explicitly call out overridden virtual functions
class plFoo : public plBar
{
public:
// New virtual function for plFoo
virtual void DoFooStuff();
// Overloaded virtual function from plBar
void DoBarStuff() override;
// Pure virtual function
virtual void NotImplemented() = 0;
};
Use deleted functions rather than declaring disabled functions private:
class plFoo
{
public:
plFoo();
~plFoo();
// Disable copying
plFoo(const plFoo&) = delete;
void operator=(const plFoo&) = delete;
};
Template declaration should be on its own line.
template <typename _T>
void Foo(const _T& x)
{
// Stuff
}
Public function names should start with an upper case letter, and then be camelCase. Classes should have a prefix (usually 'pl') and then be followed by camelCase.
Member variables should start with an 'f' ("field") and then be camelCase. Global variables should be avoided, but may use 'g' followed by camelCase. Static variables should start with an 's'. Local variables and parameters have no prefix.
class plKlass
{
public:
void plKlass(int x, const char* y)
: fX(x), fY(y)
{ }
private:
int fX;
const char* fY;
};
void Bar(int x, int y)
{
int z = x y;
return z - 5;
}
Function calls and declarations should have no space before parens. Control flow statements should have a space between the keyword and the parens. Do not use parens around a return
statement's parameter.
int Foo(int x)
{
if (x < 10)
return 5;
while (x > 0)
x = DoMath(x);
return x;
}
Initializer lists should have spaces on both sides.
std::pair<int> x { 5, 10 };
Unary operators should have no space between themselves and their operand.
if (!fPointer)
return false;
Binary (and ternary) operators should have spaces on both sides.
return (x < 5 && y > 5) ? -1 : 1;
for (const auto& x : myList)
Display(x);
Just Say No (tm). It is acceptable to use other control flow tricks if absolutely positively necessary.
do {
// Stuff
if (x < y)
break;
// Other stuff
} while (false);
Use C casts whenever possible.
return static_cast<int>(5.0f);
return reinterpret_cast<const void*>("Foo");
Treat lambdas as blocks for brace placement. Captures should be explicit.
RegisterCallback(object,
[this, x](const char *message) {
ShowMessage(message, x);
});
RegisterDataProvider(
[this](plGenerator* gen) -> plData* {
if (this)
return gen->GenerateFor(this);
else
return nullptr;
});