This is an old revision of the document!
Code is written once by one person but read many times by many people. |
What this essentially boils down to is; don't make syntactic short-cuts that makes it easier to write the code if it makes it harder to read the the code.
Always write comments to logical blocks in the code that explains for example what a for loop does or how a couple of function calls interact.
Never make if statements or loops that can't be displayed within a single screen. If they are this long rethink the code structure.
Functions should likewise be possible to show on a single screen. If longer split the function into several smaller functions. This will make logic of the code stand out and ultimately make it easier to read the code.
Always use C++11 code.
Use BSD/Allman style. This basically boils down to 'curly braces always on a new line' with the only exception being switch statements (see later section) as this:
void function() { for(int i = 0; i < 100; ++i) { foo(i); } }
This code will make emacs behave in this manner:
(setq c-default-style "bsd" c-basic-offset 4)
Vim apparently applies this behaviour by default.
Always use curly braces on if statements… even one-liners…
if(this) { then_that(); }
Plain switch case:
switch(value) { case 1: break; case 2: break; }
If switching over an enum never use 'default' since this will make the compiler unable to warn about missing cases that arise if the enum is expanded.
If a variable needs to be declared inside a case further braces are needed. They should be indented as follows:
switch(value) { case 1: { int my_value = 42; } break; case 2: break; }
Note that the break is still positioned outside the closing brace to make it easy to spot missing breaks.
Use protected instead of private as this makes unittesting easier (or at all possible). Use inheritance an initialisations on seperate lines with the colon/comma in the beginning of the lines.
By example:
class MyClass : public SomeBaseClass , public SomeOtherBaseClass { public: MyClass(int someMember); protected: int some_member; };
MyClass::MyClass(int someMember) : someMember(someMember) , SomeBaseClass(someMember) , SomeOtherBaseClass(someMember) { // ... }
If methods are overloaded always use the 'override' keyword and write a comment in the header file where the original method were:
class MyClass : public SomeBaseClass , public SomeOtherBaseClass { public: // From SomeBaseClass void someMethod() override; void someMethod2() override; // From SomeOtherBaseClass void someOtherMethod() override; void someOtherMethod2() override; };
Pointer stars and reference ampersands must be placed to the left without space after the type:
int a = 42; int* b = &a; int& c = a;
Use "SmartTabs", ie. tabs for indentation and spaces for alignment.
Tab-width is irrelevant as it is up to the editor to show them in whatever manner the programmer likes them.
Download smart-tabs-mode.el and cl-lib into the .emacs.d/lisp
folder and add the following lines to the .emacs
file:
(add-to-list 'load-path "~/.emacs.d/lisp/") (load-file "~/.emacs.d/lisp/cl-lib-0.5.el") (load-file "~/.emacs.d/lisp/smart-tabs-mode.el") (autoload 'smart-tabs-mode "Intelligently indent with tabs, align with spaces!") (autoload 'smart-tabs-mode-enable "smart-tabs-mode") (autoload 'smart-tabs-advice "smart-tabs-mode") (autoload 'smart-tabs-insinuate "smart-tabs-mode") (smart-tabs-insinuate 'c 'c++ 'java 'javascript 'cperl 'ruby 'nxml)
In Vim is should be possible to use Smart-Tabs mode using the following lines:
:set noet sts=0 sw=4 ts=4 :set cindent :set cinoptions=(0,u0,U0
Use
#pragma once ... code ...
and NOT the old-school
#ifndef DG_HEADER_FOO_H #define DG_HEADER_FOO_H ... code ... #endif//DG_HEADER_FOO_H
Use the new nullptr
instead of the C-style NULL.
Pre increment integers and iterators instead of post increment.
Like this:
int i = 0; ++i;
Always range-based for loops and in cases where these are not available at least use the auto keyword for the iterator type:
std::vector<int> my_vector; for(auto an_int : my_vector) { foo(an_int); }
All names MUST ALWAYS be good, non-short and descriptive.
int w = 70; // <-- BAD int window_width = 70; // <-- GOOD
The following naming schemes apply:
classes:
class UpperCaseCamelCase { };
methods:
void lowerCaseCamelCase()
variables:
int lower_case_snake_case = 42;
defines:
#define ALL_UPPERCASE_WITH_UNDERSCORES 42
The rule about when to use const is “as often as possible”. All function or methods taking objects as arguments should be passed as references and if the function or method does not modify them the argument must be declared const.
void openFile(const std::string& filename); // <-- Function doesn't modify the argument. void getPath(std::string& path) const; // <-- Method doesn't modify it's object but does modify the argument.
The const keyword is positioned to the left of the type which makes the distinguishing between a pointer to a const object and a const pointer to an object easier.
const Foo* foo // <-- a pointer to a const Foo object. Foo* const foo // <-- a const pointer to a Foo object. const Foo* const foo // <-- a const pointer to a const Foo object.
All public methods on classes must be documented with doxygen. Protected/private methods should also be documented but not nessecarily with doxygen syntax. The doxygen style to be used is “//!” for comment style and “\” as keyword marker:
//! This is a class class SomeClass { public: //! This is a method. //! \param foo The foo argument is an integer. //! \param bar The bar argument is a boolan. //! \return This method returns a float. float method(int foo, bool bar); protected: // Internal utility method for doing stuff on the coordinate (x, y). void doStuff(int x, int y); };
A lot of these guidelines are inspired by the style guide from the Ardour project.