Back to developer page.

C++ coding conventions and style guide

We try to maintain a consistent coding style because it makes reading and modifying the code easier. Our coding conventions aren't necessarily better than others (though we try to follow ones that make sense and change those that don't), but the main utility of this is consistency.

We're much stricter these days than we were, say, 10 years ago. The reason for this is that a codebase with many contributors and large size is much harder to maintain than a small one. So new code must pass tougher tests than some of the existing code. (Of course, the existing code should ideally be cleaned up more, too, but few people are motivated to work on such tasks if there are other things to do that seem more urgent.) Once code is in, it usually isn't changed for years unless we discover a bug. So we really try to put a lot of effort on making things as right as possible on the first try.

The following is not meant to be a complete description of our coding conventions. When in doubt, follow the example of the existing code.

See also the information on how and where to put ../Whitespace.

Language support

The translator runs on Python >= 3.6. The search code uses C++11 and may use all language features supported by GCC 5.4, clang 3.9, and MSVC 19.15.

General recommendations

We generally follow the recommendations in the book C++ Coding Standards: 101 Rules, Guidelines, and Best Practices by Herb Sutter and Andrei Alexandrescu. In the tracker or elsewhere, a mark of the form [SA x] is a reference to a rule in that book. For example, [SA 9] refers to Sutter and Alexandrescu's rule 9: "Don’t pessimize prematurely".


   1 // Write complete sentences ending with periods.
   3 // Use imperative if possible: "Return the factorial." is better than "Returns the factorial.".
   5 // Leave a space between the slashes and the comment.
   7 // TODO: Use this format for todo items.
   9 /*
  10   Use this style for comments spanning 
  11   multiple lines and strive to write 
  12   self-explanatory code that doesn't need 
  14 */
  17 /* For shorter multi-line comments (2-3 lines)
  18    this style is also fine. */

We generally prefer comments above the code (not next to it). If you really want to put a short comment next to the code, leave one space before and after the // slashes.

Subdirectories, namespaces and cmake plugins



CMake plugins:


Open questions:

Header file guards

Macro names for header file guards follow this algorithm:

Example: learning/state_space_sample.h becomes LEARNING_STATE_SPACE_SAMPLE_H.

Guard blocks should look like this:

   3 // ...
   4 #endif

That's all. In particular, don't add comments to the preprocessor directives and don't add further underscores.


Order includes in the following way: header corresponding to .cc file, headers from the same directory, headers from the src/search directory, headers from other directories, standard library includes, and third-party library includes. If using the using namespace std declaration, put it after all other includes. Order each group alphabetically and separate the groups by empty lines. Add an empty line between the last group and the remaining code. Here is a contrived example:

   1 #include "pattern_generation_edelkamp.h"
   3 #include "zero_one_pdbs_heuristic.h"
   5 #include "../abstract_task.h"
   6 #include "../causal_graph.h"
   8 #include "../algorithms/ordered_set.h"
   9 #include "../utils/timer.h"
  11 #include <algorithm>
  12 #include <cassert>
  13 #include <vector>
  15 #include <tree.hh>
  17 using namespace std;
  19 PatternGenerationEdelkamp::PatternGenerationEdelkamp(const Options &opts)
  20 ...

Constructors, destructors and assignment operators

Function signatures

const attributes

We generally don't make attributes of classes const. See the attached discussion for the rationale behind this convention. (This is a convention that may be changed if there is sufficient support, but while it is the way it is, we should all follow the same style.) Exceptions include:

The same rules apply to function parameters and local variables.

push_back vs. emplace_back


   1 Foo x = ...; // construct a Foo
   3 vector<Foo> foos;
   4 foos.push_back(move(x));    // move the constructed Foo into the container
   5 foos.emplace_back(44, 22);  // Foo has a constructor that takes two ints. Use emplace_back to directly construct the object inside the container.


Passing and storing tasks

Conceptually, it's less clear that this is desirable, but with our current design you cannot create a delegating task without (co-) owning the task.


Derive custom exception classes from utils::Exception.


FastDownward: ForDevelopers/CodingConventions (last edited 2021-09-16 16:27:08 by FlorianPommerening)