Skip to content

google style guide

r4d2 edited this page Jan 10, 2014 · 2 revisions

Additional practice guidelines

The following guidelines are mostly based on the Google C++ Style Guide. We modified it, because we don't agree with all of the policies from the Google Style Guide.

[TOC]

Header Files

#define guards

Every header file has to come with a #define guard of the following form:

#ifndef <PROJECT>_<PATH>_<FILE>_H_
#define <PROJECT>_<PATH>_<FILE>_H_

...

#endif /* <PROJECT>_<PATH>_<FILE>_H_ */

DON'T use #pragma once

Function parameter ordering

  1. Inputs
  2. Outputs

Order of includes

All #includes have to go to the top of the file (after the include guard). Use the following order:

  1. C library
  2. C++ (STL) library
  3. other libraries
  4. includes from this project

Scoping

Namespaces

DON'T use the using directive.

Always use namespaces: everything outside of a main file must be enclosed in the project's namespace.

Nested Classes

Try to avoid and use only if absolutely necessary.

Scope of functions

Try to avoid global functions. Prefer nonmember functions within a namespace or static member functions to global functions.

Local Variables

Place a function's local variables in the narrowest scope possible, and initialize variables in the declaration.

Static and Global Variables

Static or global variables of class type are forbidden: they cause hard-to-find bugs due to indeterminate order of construction and destruction. However, such variables are allowed if they are constexpr: they have no dynamic initialization or destruction.

Classes

Don't implement complex algorithms in class methods. Rather implement them as nonmember methods inside the projects namespace (or sub-namespace).

Constructors

  • Avoid doing complex initialization in constructors (in particular, initialization that can fail or that requires virtual method calls).

  • Always declare and define constructors for your classes that initialize ALL member variables that are not initialized in-class. If you do not, the default constructor might not properly initialize all member variables.

  • Provide a copy constructor and assignment operator only when necessary. Otherwise, disable them with DISALLOW_COPY_AND_ASSIGN.

  • Use delegating and inheriting constructors when they reduce code duplication.

Structs vs. Classes

Use a struct only for passive objects that carry data; everything else is a class.

Inheritance

  • All pure interfaces must end with the Interface suffix.
  • Multiple inheritance is only permitted when at most one of the base classes has an implementation, all other bases classes must be pure interfaces.

Operator Overloading

Do not overload operators except when strictly semantically equivalent.

Access control

Make data members private and provide access to them via getter and setter methods.

Example:

class Foo
{
public:
    int getBar();
    void setBar(int bar);
private:
    int bar;
}

Write small functions

Prefer small functions, don't implement complex algorithms in class member functions.

Other C++ features

Reference arguments

All parameters passed by reference must be labeled const. Try to use references where ever possible (avoiding unnecessary copies).

Function overloading

Use overloaded functions (including constructors) only if a reader looking at a call site can get a good idea of what is happening without having to first figure out exactly which overload is being called.

Default Arguments

We do not allow default function parameters.

Friends

Minimize the usage of friend classes and functions.

Exceptions

We will use C++ exceptions.

Casting

Use static_cast<>().

DON'T use C-style casting (i.e. y = (int)x; y = int(x);).

Pre/Post increment

Use prefix form (++i) where ever they are interchangeable (i.e. loops).

const

  • Use constexpr and const whenever it makes sense.

Integer types

Allowed are only the base types:

  • char
  • signed char
  • int
  • unsigned int

Use ints only when the actual bit width is not of importance (i.e. 32 bit vs. 64 bit does NOT matter). If in doubt, use the precise-width types (see below) instead.

NOT allowed are especially the types:

  • short
  • long
  • long int
  • long long

Use the precise-width integer types from <stdint.h> instead, e.g. uint64_t, int16_t, etc.

32-bit vs. 64-bit

TODO are we sure that our algorithm will only work on 64 bit?

Be aware of compatibility between these systems.

Preprocessor Macros

Avoid when ever possible. Use constexpr functions, inline functions and constexpr variables instead.

0 and NULL

Use the following literals for null:

  • integers: 0
  • reals: 0.0
  • pointers: nullptr (avoid the NULL macro)
  • chars: '\0'

sizeof

Use sizeof(varname) instead of sizeof(type).

auto

Use the auto type for STL iterators inside of loops. Try to avoid auto as much as possible otherwise. The auto keyword is encouraged in situations like:

std::vector<int> a(10);

// use:
for (auto it : a)
{
    // ...
}

// avoid:
for (std:vector<int>::iterator it : a)
{
    // ...
}

// especially avoid the old for-loop style:
for (std::vector<int>::iterator it = a.begin(); it != a.end(); ++it)
{
    // ...
}

Brace initialization

You may use brace initialization, e.g.:

std::vector<int> a = {1, 2, 3, 5};

Boost

Usage of boost libraries is allowed.

C++11

We are using features of the C++11 standard.