Most of the style and formating guide is enforced by clang-format and the rest are documented in this file. Since I did not start to enforce these rules until later stage of development, some parts of the codebase are inconsistent. If you discover such case, please submit a PR.
Keep class, struct, and enum names in PascalCase.
class AppleManager { /* ... */ };
enum class FruitKind { Sweet, Sour };Define free functions and methods with lower_snake_case identifiers.
bool is_ripe(const Fruit& fruit);Use lower_snake_case for locals and parameters; append _ to private data members to signal scope.
int max_items;Use SCREAMING_SNAKE for constexpr variables.
constexpr uint32_t FLAG_MASK;class Basket {
private:
int fruit_count_;
public:
int capacity;
};Variables and struct and class members representing size, length or count should use the following suffixes:
_num: The number of items in an array, vector or other container._count: Accumulated, counted values (such as the number of items in a linked-list)._size: Size in bytes._len: For strings (the length of the string without it's null byte, as used instrlen).
Enforce const strictly everywhere except inside a function/class method.
int sum(const std::vector<int>& vec){
// const is optional in function body
int element_num = vec.size();
// ...
}Always use brackets in if, for construct.
// Never skip {}
if (true){
// ...
}Explicitly write out private/public in each sections and follow below layout.
class Basket {
public:
// anything that is not a method. i.e. class member, constexpr variable, using alias
int private_var_;
private:
// anything that is not a method. i.e. class member, constexpr variable, using alias
int public_var_;
public:
// private class method
int count();
private:
// public class method
void clear();
};Other than interfacing with external libraries, do not use exception. There are two reasons for this decision:
- The code interacts with many C-style numerical libraries, so avoiding exception style error handling make things consistent.
- Exception throwing is hidden from function signature. Which makes it difficult to reason about hidden code path.
Instead, return bool, std::optional, or nullptr to indicate failure. If detail information is valuable, use spdlog library to log it to stdout.
std::optional<int> func_that_might_fail(); If a class constructor has a change to fail, use factory method instead.
class Foo{
private:
// Move default ctor to private
Foo() = default;
public:
// Factory function should be static and returns the optional of class type.
// The name should be make_<class name>.
static std::optional<Foo> make_foo();
}Start public headers and major interfaces with /// blocks that include @brief, @param, and @return.
/// @brief Count pieces of fruit in the basket.
/// @param basket Storage container to inspect.
/// @return Number of fruit items currently stored.
int count_fruit(const Basket& basket);For code comments, use //.
Tips: You can feed misc/llm_guidelines/cpp_comment.md to generate the initial comment/doc. Make sure to review it though.