| Good | Bad |
|---|---|
| ```cpp // crepe startup message std::string message = "Hello, world!"; ``` | ```cpp // crêpe startup message std::string message = "こんにちは世界"; ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo {}; ``` | ```cpp class Cars {}; ``` |
| Good | Bad |
|---|---|
| ```cpp int add(int a, int b) { // add numbers int out = a + b; return out; } ``` | ```cpp int add(int a, int b) { int out = a + b; // add numbers return out; } ``` |
| Good | Bad |
|---|---|
|
```cpp
#include |
```cpp
#include |
.hpp) is included
at the bottom of the regular header (.h)
| Good | Bad |
|---|---|
|
Foo.h:
```cpp
#pragma once
template |
Foo.h:
```cpp
#pragma once
template |
using namespace may not be used in header files (.h, .hpp), only
in source files (.cpp).
| Good | Bad |
|---|---|
| example.h: ```cpp namespace crepe { void foo(); } ``` example.cpp: ```cpp #include "example.h" using namespace crepe; void foo() {} ``` |
example.h:
```cpp
namespace crepe {
template |
get_
and set_.
| Good | Bad |
|---|---|
| ```cpp class Foo { public: int get_speed() const; void set_speed(int speed); private: int speed; }; ``` | ```cpp class Foo { public: int speed() const; void set_speed(int speed); private: int speed; }; ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo { Foo & get_instance() { static Foo instance; return instance; } }; ``` | ```cpp Foo Foo::instance {}; class Foo { static Foo instance; Foo & get_instance() { return Foo::instance; } }; ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo { int speed = 0; }; ``` | ```cpp class Foo { Foo() : speed(0) {} int speed; }; ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo { public: Foo() : bar("baz") {} private: std::string bar; }; ``` | ```cpp class Foo { public: Foo() : bar(0) {} private: int bar; }; ``` |
| Good | Bad |
|---|---|
| ```cpp struct Foo { int bar = 0; std::string baz; }; ``` | ```cpp struct Foo { int bar; std::string baz; }; ``` |
| Good | Bad |
|---|---|
| ```cpp class Bar; class Foo { Bar & bar; }; ``` | ```cpp #include "Bar.h" class Foo { Bar & bar; }; ``` |
.h header, and
defined in a matching .hpp header.
| Good | Bad |
|---|---|
|
add.h:
```cpp
template |
add.h:
```cpp
template |
| Good | Bad |
|---|---|
| ```cpp enum Color { Red, Green, Blue, }; ``` | ```cpp enum Color { Red, Green, Blue }; ``` |
#pragma should be used instead of include guards
| Good | Bad |
|---|---|
| ```cpp #pragma once // ... ``` | ```cpp #ifndef __INCLUDED_H #define __INCLUDED_H // ... #endif ``` |
std::move
| Good | Bad |
|---|---|
| ```cpp using namespace std; string foo = "bar"; ref_fn(std::move(foo)); ``` | ```cpp using namespace std; string foo = "bar"; ref_fn(move(foo)); ``` |
| Good | Bad |
|---|---|
| ```cpp void foo(const Point & p); ``` | ```cpp void foo(Point & p); void bar(Point p); ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo { public: Foo(); ~Foo(); Foo(Foo &&) noexcept; Foo & operator = (const Foo &); Foo & operator = (Foo &&) noexcept; }; ``` | ```cpp class Foo { public: Foo(); ~Foo(); }; ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo { public: int get_value() const; void set_value(int new_value); const std::string & get_name() const; void set_name(const std::string & new_name); private: int value; std::string name; }; ``` | ```cpp class Foo { public: int get_value(); void set_value(int new_value); std::string get_name(); void set_name(std::string new_name); private: int value; std::string name; }; ``` |
| Good | Bad |
|---|---|
| ```cpp MyClass.h MyClass.cpp MyClass.hpp ``` | ```cpp my_class.h myClass.cpp my-class.hpp ``` |
| Good | Bad |
|---|---|
| ```cpp class Foo { public: int get_value() const { return 42; } }; ``` | ```cpp class Foo { public: int calculate_value() const { int result = 0; // complex calculation return result; } }; ``` |
<>) only for including system headers and
double quotes ("") for including other engine files.
> [!NOTE]
> Only files in the examples folder should include engine headers with angle
> brackets
| Good | Bad |
|---|---|
|
```cpp
#include |
```cpp
#include |
| Good | Bad |
|---|---|
|
```cpp
auto foo = std::make_unique | ```cpp Foo* foo = new Foo(); // ... delete foo; ``` |
malloc,
calloc, free)
| Good | Bad |
|---|---|
| ```cpp Foo * foo = new Foo(); delete foo; ``` | ```cpp Foo * foo = (Foo *) malloc(sizeof(Foo)); free(foo); ``` |
this->
| Good | Bad |
|---|---|
| ```cpp void Foo::bar() { } void Foo::set_value(int value) { this->value = value; this->bar(); } ``` | ```cpp void Foo::bar() { } void Foo::set_value(int new_value) { value = new_value; bar(); } ``` |
true/false literals instead of
0/1
| Good | Bad |
|---|---|
| ```cpp bool foo = true; bool bar = false; ``` | ```cpp bool foo = 1; bool bar = 0; ``` |
friend relations are documented
| Good | Bad |
|---|---|
| ```cpp //! ComponentManager calls the private constructor of this class friend class ComponentManager; ``` | ```cpp friend class ComponentManager; ``` |
| Good | Bad |
|---|---|
| ```cpp unsigned long long foo(); ``` | ```cpp uint64_t foo(); ``` |
<stdexcept>)
| Good | Bad |
|---|---|
|
```cpp
#include | ```cpp if (foo == nullptr) { std::cout << "What is wrong" << std::endl; exit(1); } ``` |
| Good | Bad |
|---|---|
| ```cpp Foo::bar() { if (...) throw std::runtime_error("Foo: big error!"); } ``` | ```cpp Foo::bar() { if (...) throw std::runtime_error("big error!"); } ``` |
Component should be
protected and ComponentManager should be declared as a friend
class.
| Good | Bad |
|---|---|
| ```cpp class MyComponent : public Component { protected: MyComponent(...); //! Only ComponentManager is allowed to create components friend class ComponentManager; }; ``` | ```cpp class MyComponent : public Component { public: MyComponent(...); }; ``` |
std::format should be used instead of C-style format specifiers
| Good | Bad |
|---|---|
| ```cpp std::string message = std::format("Hello, {}", name); dbg_logf("Here too: {}", 3); throw std::runtime_error(std::format("Or here: {}", 5)); ``` | ```cpp char message[50]; sprintf(message, "Hello, %s", name); ``` |
.h files (not only in
.cpp and .hpp files)
| Good | Bad |
|---|---|
| Foo.h: ```cpp void foo(int bar); ``` Foo.cpp: ```cpp void foo(int bar) { // ... } ``` | Foo.h: ```cpp void foo(int); ``` Foo.cpp: ```cpp void foo(int bar) { // ... } ``` |
.front() or .back()
instead of by index
| Good | Bad |
|---|---|
|
```cpp
vector |
```cpp
vector |
| Good | Bad |
|---|---|
| ```cpp /** * \brief do something * * \param bar Magic number */ void foo(int bar); ``` | ```cpp /** * @brief do something * * @param bar Magic number */ void foo(); ``` |
\brief description
| Good | Bad |
|---|---|
| ```cpp Foo(); virtual ~Foo(); ``` | ```cpp //! Create instance of Foo Foo(); //! Destroy instance of Foo virtual ~Foo(); ``` |
| Good | Bad |
|---|---|
| ```cpp /** * \param bar Reference to Bar */ void foo(const Bar & bar); ``` | ```cpp /** * \param[in] bar Reference to Bar */ void foo(const Bar & bar); ``` |
| Good | Bad |
|---|---|
| ```cpp // singleton Foo(const Foo &) = delete; Foo(Foo &&) = delete; Foo & operator=(const Foo &) = delete; Foo & operator=(Foo &&) = delete; ``` | ```cpp //! Deleted copy constructor Foo(const Foo &) = delete; //! Deleted move constructor Foo(Foo &&) = delete; //! Deleted copy assignment operator Foo & operator=(const Foo &) = delete; //! Deleted move assignment operator Foo & operator=(Foo &&) = delete; ``` |