This document describes the code style of AnKi 3D Engine. Comments ======== All comments are C++ like: // Some comment And for doxygen comments: /// @brief blah blah /// @param blah blah Naming Conventions ================== **Variables, functions and methods** are lower camelCase. functionDoSomething(someVariableA, someVariableB); All **types** are PascalCase and that includes classes, structs, typedefs and enums. enum MyEnum {...}; class MyClass {...}; using MyType = int; All **constant expressions** are SCREAMING_SNAKE_CASE and that includes enumerants. constexpr int MY_CONSTANT = ...; enum MyEnum { ENUMERANT_A }; All **macros and defines** should be SCREAMING_SNAKE_CASE and they should have an `ANKI_` prefix. ANKI_ASSERT(...); #define ANKI_MAX_SOMETHING ... All **template arguments** should start with `T`. template The **source files** are always PascalCase. ThreadHive.h MyShaderProgram.ankiprog All **function and method names** should form a sentence with at least one verb. doSomething(...); getSomething(); calculateSomething(...); **No hungarian notations** with 2 exceptions. - All member variables have the `m_` prefix. - All global variables have the `g_` prefix. C++ rules ========= **Always use strongly typed enums**. If you need to relax the rules use the `ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS` macro. enum class MyEnum : uint {...}; ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(MyEnum, inline); **Never use `typedef`** to define types. Use `using` instead. using U32 = uint32_t; using Func = void(*)(int, int); **Never use C-style casting**. Use static_cast, reinterpret_cast or const_cast for most cases and constructor-like cast for fudmental types. Derived* d = static_cast(base); uint i = uint(1.1f); // uint is fudmental type **Always use `constexpr`** when applicable. Never use defines for constants. constexpr uint SOME_CONST = ...; **Never use `struct`** and always use `class` instead. Since it's difficult to come up with rules on when to use struct over class always use class and be done with it. class MyTrivialType { public: int m_x; int m_y; }; **Avoid using `auto`**. It's only allowed in some templates and in iterators. auto makes reading code difficult. **Includes should always have the full file path**. This avoids issues with files of similar name. Non-AnKi includes follow AnKi includes. #include #include #include #include **Never use public nested classes**. Only private nested classes are allowed. Nested classes cannot be forward declared. class MyClass { public: // NO!!!!!!!!!!! class Nested {...}; private: // It's fine class Nested {...}; // Also fine class { ... } m_myUnamedThing; }; Try to **use `explicit`** in constructors for extra safety. Don't use explicit on copy constructors. AnKi uses **const correctness** throughout and that's mandatory. Always use `const`. The only place where you don't have to is for function and method parameters. uint doSomething(uint noNeedForConst) { const uint bla = noNeedForConst + 10; return blah; } **Access types in a class have a specified order**. First `public` then `protected` and last `private`. There are some exceptions where this rule has to break. class MyClass { public: ... protected: ... private: ... }; Always **use AnKi's fudmental types** (U32, I32, F32, Bool etc etc). For integers and if you don't care about the size of the integer you can use the type `U` for unsinged or `I` for signed. Both of them are at least 32bit. for(U32 i = 0; i < 10; ++i) {...} If you have to overload the operator Bool always use **`explicit operator Bool` operator** overloading. explicit operator Bool() const {...} The use of **references and pointers** is govern by some rules. Always use references except when you transfer or share ownership where you should use pointers. Pointers are also allowed for optional data that can be nullptr. // ptr is a pointer so you CAN NOT destroy it after a call to doSomething is done // ref is a reference so you CAN destroy it after a call to doSomething is done void Foo::doSomething(TypeA* ptr, TypeB& ref) { // Store the ptr somewhere m_someMember = ptr; // Won't store the ref ref += ...; } Always **use `nullptr`**. void* ptr = nullptr; **Never use C style arrays**. Use the `Array<>` template instead. Array myArray; **Don't use STL**. AnKi has a replacement for most STL templates. There are some exceptions though. - Can use `type_traights`. - Some from `utility` eg std::move. - Some from `algorithm` eg std::sort. Always try to **comment parts of the source code**. Self documenting code is never enough. Always use `override` or `final` on virtual methods and try to use `final` on classes when applicable. class Foo final { public: void myVirtual(...) override {...} }; Code formatting =============== clang-format deals with code formatting. To format the whole source tree type the following in a terminal: $ cd /path/to/anki $ ./tools/format_source.sh If you need to format on Windows do the same from a WSL terminal. Some cases that are not handled by clang-format follow. **Always use curly braces** on single line expressions. // NO!!!!!!!!!!! if(something) doSomething(); // YES!!!!!!!!!!!!!! if(something) { doSomething(); } Always place the **condition of a conditional ternary operator** inside parenthesis. // NO!!!!!!!!!!! a = b ? 1 : 0; // YES!!!!!!!!!!!!!! a = (b) ? 1 : 0;