| | 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 | }}} |