| 48 | === Header Best Practices === |
| 49 | |
| 50 | While resolving some expensive headers, a few best practices stood out to reduce compilation times without regressing runtime performance: |
| 51 | |
| 52 | ==== Forward-declare all the things ==== |
| 53 | |
| 54 | Forward-declaring types used by your class's methods allows clients who don't call those methods to not incur the compile-time cost of including those types' headers. |
| 55 | |
| 56 | C++ class members must be fully defined, so e.g. consider using `UniqueRef<MyClass>`, and forward-declaring `MyClass`, instead of including `MyClass.h`. |
| 57 | |
| 58 | C++ function parameters and return values do not need to be fully defined, and can be forward-declared. So e.g. if `MyClass` function parameter or return value, consider forward-declaring `MyClass`, instead of including `MyClass.h`. |
| 59 | |
| 60 | C++ virtual functions are rarely able to be inlined, even if decorated with `inline`, so avoid inline definitions of virtual functions. So e.g. if defining a virtual base class method that returns a `Ref<MyClass>`, put the default implementation inside the class implementation file. |
| 61 | |
| 62 | ==== Avoid class-scoped enums ==== |
| 63 | |
| 64 | When defining a public enumeration for a class, do so at namespace scope rather than inside the class, and always specify an explicit enum size. E.g.: |
| 65 | |
| 66 | Bad: |
| 67 | {{{ |
| 68 | #!c++ |
| 69 | // MyClass.h |
| 70 | class MyClass { |
| 71 | public: |
| 72 | enum Options { |
| 73 | Option1, |
| 74 | Option2, |
| 75 | Option3, |
| 76 | }; |
| 77 | ... |
| 78 | }; |
| 79 | }}} |
| 80 | |
| 81 | Good: |
| 82 | {{{ |
| 83 | #!c++ |
| 84 | // MyClass.h |
| 85 | enum class MyClassOptions : uint8_t { |
| 86 | Option1, |
| 87 | Option2, |
| 88 | Option3, |
| 89 | }; |
| 90 | class MyClass { |
| 91 | public: |
| 92 | ... |
| 93 | }; |
| 94 | }}} |
| 95 | |
| 96 | This allows clients to forward declare the enum type, rather than include `MyClass.h`: |
| 97 | {{{ |
| 98 | #!c++ |
| 99 | // YourClass.h |
| 100 | enum class MyClassOptions : uint8_t; |
| 101 | class YourClass { |
| 102 | void functionWithMyClassOptions(MyClassOptions); |
| 103 | }; |
| 104 | }}} |
| 105 | |
| 106 | ==== Add Inlines.h headers ==== |
| 107 | |
| 108 | When explicitly inlining a function definition for performance reasons, and that definition requires including an external header, putting the inline definition in an Inlines.h header file. Annotate the class method declaration with `inline`, which will cause a compiler warning if the Inline.h header is not included by the caller. E.g.: |
| 109 | |
| 110 | Bad: |
| 111 | {{{ |
| 112 | #!c++ |
| 113 | // MyClass.h |
| 114 | #include "YourClass.h" |
| 115 | class MyClass { |
| 116 | public: |
| 117 | YourClass& yourClassGetFoo() { return YourClass::foo(); } |
| 118 | }; |
| 119 | }}} |
| 120 | |
| 121 | Good: |
| 122 | {{{ |
| 123 | #!c++ |
| 124 | // MyClass.h |
| 125 | class MyClass { |
| 126 | public: |
| 127 | inline YourClass& yourClassGetFoo(); |
| 128 | }; |
| 129 | |
| 130 | // MyClassInlines.h |
| 131 | inline YourClass& MyClass::yourClassGetFoo() { return YourClass::foo(); } |
| 132 | }}} |