Mercurial > template
view STYLE_CPP.md @ 3:44f548c50e16
Typo
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 01 Feb 2017 10:59:14 +0100 |
parents | 1e34b51d9c52 |
children | 41dac98beeb2 |
line wrap: on
line source
PROJECT NAME C++ CODING STYLE ============================= Style ----- - Always use 4 spaces as indentation, - Do not exceed 120 characters for lines of code, - Do not exceed 80 characters for comments, - Never write two blank consecutives blank lines, ### Braces Braces follow the K&R style, they are never placed on their own lines except for function definitions. In addition to the K&R style, they are required everywhere even if a block contains only one statement. if (condition) { apply(); add(); } else { ok(); } if (condition) { validate(); } And a lambda has its braces on the same lines too: sort([&] (object&) { return true; }); ### Spaces Each reserved keyword (e.g. `if`, `for`, `while`) requires a single space before its argument. Normal function calls do not require it. if (foo) { destroy(sizeof (int)); } ### References and pointers References and pointers are always next to the type name and not the variable. T& get(const std::string& name); int* p = &x; ### Naming - English names, - Member variables starts with `m_`, - No hungarian notation. Everything is in `underscore_case` except template parameters and macros. #if defined(FOO) # include <foo.hpp> #endif namespace baz { class object { private: std::string m_name; public: inline const std::string& name() const noexcept { return m_name; } }; template <typename Archive> void open(const Archive& ar) { bool is_valid = false; } } // !baz ### Header guards Do not use `#pragma once`. Header guards are usually named **PROJECT_COMPONENT_FILENAME_HPP**. #ifndef FOO_COMMON_UTIL_HPP #define FOO_COMMON_UTIL_HPP #endif // !FOO_COMMON_UTIL_HPP ### Enums Enumerations constants are always defined in separate line to allow commenting them as doxygen. Enum class are encouraged. enum class color { blue, red, green }; ### Files - Use `.cpp` and `.hpp` as file extensions, - Filenames are all lowercase. ### Comments Avoid useless comments in source files. Comment complex things or why it is done like this. However any public function in the .hpp **must** be documented as doxygen without exception. /* * Multi line comments look like * this. */ // Short comment Use `#if 0` to comment blocks of code. #if 0 broken_stuff(); #endif ### Includes The includes should always come in the following order. 1. C++ headers 2. C header 3. Third party libraries 4. Application headers in "" #include <cstring> #include <cerrno> #include <sys/stat.h> #include <libircclient.h> #include "foo.h" **Note**: always use C++ headers for C equivalent, stdio.h -> cstdio, etc. ### Commit messages Commit messages are written using the following syntax: Topic: short message less than 80 characters Optional additional description if needed. Replace `Topic` with one of the following: - **CMake**: for the build system, - **Docs**: for the documentation, - **Misc**: for miscellaneous files, - **Tests**: for the unit tests. Programming ----------- ### C language Do not use old C stuff like `void *`, `srand/rand`, `printf` or anything that can be rewritten in modern C++. ### RTTI Usage of `dynamic_cast` and `typeid` are completely disallowed in any shape of form. ### Arguments It is recommended to pass parameters by value or const reference. Usage of non-const reference as output parameter is **discouraged** and should be avoided in many case because it does not allow chaining of expressions like: std::cout << reverse(upper(clean(" hello world! "))) << std::endl; If your function is designed to return a modified value passed as argument, it is better to take it by value and modify it directly. std::string clean(std::string input) { if (!input.empty() && input.back() == '\r') { input.pop_back(); } return input; } Never pass primitive types as const value. ### Assertions Use the `assert` macro from the cassert header file to verify programming errors. For example, you may use `assert` to verify that the developer access the data between the bounds of an array: T& operator[](unsigned index) { assert(index < m_length); return m_data[index]; } The `assert` macro is not meant to check that a function succeeded, this code must not be written that way: assert(listen(10)); ### Exceptions You must use exceptions to indicate an error that was unexpected such as: - Failing to open a file, - I/O unexpected errors, - Parsing errors, - User errors. You may use the C++ standard exceptions defined in the stdexcept header but if you need to carry more data within your exception, you should derive from `std::exception`. ### Free functions Basic utility functions should be defined in a namespace as a free function not as a static member function, we're doing C++ not Java. Example: namespace util { std::string clean(std::string input); } // !util ### Variables initialization Use parentheses to initialize non primitive types: throw std::runtime_error("foo"); my_class obj("bar"); Use brace initialization when you want to use an initializer list, type elision: std::vector<int> v{1, 2, 3}; foo({1, 2}); // type deduced return { "true", false }; // std::pair returned Use the assignment for primitive types: int x = 123; bool is_valid = true; ### Classes Classes are usually defined in the following order: 1. Public inner types (enums, classes), 2. Protected/private members 3. Public functions class foo { public: enum class type { a, b }; private: int m_member{0}; public: void some_function(); } ### Structs Do not use C structs unless you have very good reason to do so. If you want to pack some data, just use `class` and make all fields public. class point { public: int x; int y; }; ### Return The preferred style is to return early in case of errors. That makes the code more linear and not highly indented. This code is preferred: if (a_condition_is_not_valid) { return nullptr; } if (an_other_condition) { return nullptr; } auto x = std::make_shared<object>(); x->start(); x->save(); return x; Additional rules: - Do never put parentheses between the returned value, - Do not put a else branch after a return.