Coding Style Guidelines¶
Choice of Language¶
Ab is written in C++14 with minimal standard library usage. In particular, be suspicious of newer standard library APIs introduced since C++11. Ab is written without exceptions.
Tooling and scripts should be written in python3.
Formatting Code¶
Ab uses clang-format. Always run clang-format on every commit.
Namespaces, Includes, and Project Layout¶
Project Configuration Headers¶
Configuration headers must be included at the top of every single source.
Configuration headers will change system APIs, and MUST be included BEFORE any system header.
Config.hpp is generated by cmake, and contains all configuration defines.
Namespaces and Nesting¶
All code should be under the top level project namespace. Use inner namespaces sparingly. Namespaces should almost exactly mimic the project layout.
Avoid nesting indentifers. Try to use globally unique indentifiers instead.
Example:
// Everything under the project namespace
namespace Ab {
class HeapConfig {}; // good - not nested
class Heap {
class Config {}; // bad - nested and nonunique name.
};
} // namespace Ab
Includes and Headers¶
There is one top-level include directory per project. All public headers are grouped in a project subdirectory. Always write include directives relative to the top-level include directory. The project name must prefix every include.
Example:
#include <Ab/Config.hpp> // Configuration first
#include <Ab/*.hpp> // Internal headers, alphabetical, with the project prefix
#include <external.hpp> // External headers, alphabetical
#include <system> // System and standard headers, last.
Writing Classes¶
Naming¶
Classes, namespaces, and structs are all TitleCased. Only the first letter of an acronym should be uppercased.
Structs vs Classes¶
Use struct for simple POD-style objects. Use class when the object is complex.
Fields, Getters, and Setters¶
private and protected fields are named with trailing underscores. public fields don’t have underscores.
Name the accessors after the field, without trailing underscore.
Setters should take a single value, and return *this
, implementing a fluent interface.
Example:
class Array {
public:
inline constexpr auto size() const -> std::size_t {
return size_;
}
inline auto size(std::size_t x) -> Array& {
size_ = x;
return *this;
}
private:
std::size_t size_;
};
Constants, Enums, and Macros¶
Code should be const by default.
Constants and macros are written as MY_CONSTANT
. Use static const constexpr
for constants,
do not use macros.
Use enum class
whenever possible.
Place compilation flags in the config header, do not add definitions to the command line.
Do not introduce a macro without a very good reason. Since macros cannot be namespaced, prefix all macros with the project name.