cpp_usage_guidelines.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. .. _doc_cpp_usage_guidelines:
  2. C++ usage guidelines
  3. ====================
  4. Rationale
  5. ---------
  6. Since Godot 4.0, the C++ standard used throughout the codebase is a subset of
  7. **C++17**. While modern C++ brings a lot of opportunities to write faster, more
  8. readable code, we chose to restrict our usage of C++ to a subset for a few
  9. reasons:
  10. - It makes it easier to review code in online editors. This is because engine
  11. contributors don't always have access to a full-featured IDE while reviewing
  12. code.
  13. - It makes the code easier to grasp for beginner contributors (who may not be
  14. professional C++ programmers). Godot's codebase is known to be easy to learn
  15. from, and we'd like to keep it that way.
  16. To get your pull request merged, it needs to follow the C++ usage guidelines
  17. outlined here. Of course, you can use features not allowed here in your own C++
  18. modules or GDExtensions.
  19. .. note::
  20. Prior to Godot 4.0, the C++ standard used throughout the codebase was C++03,
  21. with a handful of C++14 extensions. If you are contributing a pull request
  22. to the `3.x` branch rather than `master`, your code can't use C++17 features.
  23. Instead, your code must be able to be built with a C++14 compiler.
  24. The guidelines below don't apply to third-party dependencies, although we
  25. generally favor small libraries instead of larger solutions. See also
  26. :ref:`doc_best_practices_for_engine_contributors`.
  27. .. seealso::
  28. See :ref:`doc_code_style_guidelines` for formatting guidelines.
  29. Disallowed features
  30. -------------------
  31. **Any feature not listed below is allowed.** Using features like ``constexpr``
  32. variables and ``nullptr`` is encouraged when possible. Still, try to keep your
  33. use of modern C++ features conservative. Their use needs to serve a real
  34. purpose, such as improving code readability or performance.
  35. .. _doc_cpp_godot_types:
  36. Standard Template Library
  37. ~~~~~~~~~~~~~~~~~~~~~~~~~
  38. We don't allow using the `STL <https://en.wikipedia.org/wiki/Standard_Template_Library>`__
  39. as Godot provides its own data types (among other things).
  40. See :ref:`doc_faq_why_not_stl` for more information.
  41. This means that pull requests should **not** use ``std::string``,
  42. ``std::vector`` and the like. Instead, use Godot's datatypes as described below.
  43. A 📜 icon denotes the type is part of :ref:`Variant <doc_variant_class>`. This
  44. means it can be used as a parameter or return value of a method exposed to the
  45. scripting API.
  46. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  47. | Godot datatype | Closest C++ STL datatype | Comment |
  48. +========================+==========================+=======================================================================================+
  49. | ``String`` 📜 | ``std::string`` | **Use this as the "default" string type.** ``String`` uses UTF-32 encoding |
  50. | | | to improve performance thanks to its fixed character size. |
  51. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  52. | ``StringName`` 📜 | ``std::string`` | Uses string interning for fast comparisons. Use this for static strings that are |
  53. | | | referenced frequently and used in multiple locations in the engine. |
  54. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  55. | ``Vector`` | ``std::vector`` | **Use this as the "default" vector type.** Uses copy-on-write (COW) semantics. |
  56. | | | This means it's generally slower but can be copied around almost for free. |
  57. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  58. | ``LocalVector`` | ``std::vector`` | Closer to ``std::vector`` in semantics. In most situations, ``Vector`` should be |
  59. | | | preferred. |
  60. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  61. | ``Array`` 📜 | ``std::vector`` | Values can be of any Variant type. No static typing is imposed. |
  62. | | | Uses shared reference counting, similar to ``std::shared_ptr``. |
  63. | | | Uses Vector<Variant> internally. |
  64. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  65. | ``TypedArray`` 📜 | ``std::vector`` | Subclass of ``Array`` but with static typing for its elements. |
  66. | | | Not to be confused with ``Packed*Array``, which is internally a ``Vector``. |
  67. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  68. | ``Packed*Array`` 📜 | ``std::vector`` | Alias of ``Vector``, e.g. ``PackedColorArray = Vector<Color>``. |
  69. | | | Only a limited list of packed array types are available |
  70. | | | (use ``TypedArray`` otherwise). |
  71. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  72. | ``List`` | ``std::list`` | Linked list type. Generally slower than other array/vector types. Prefer using |
  73. | | | other types in new code, unless using ``List`` avoids the need for type conversions. |
  74. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  75. | ``FixedVector`` | ``std::array`` | Vector with a fixed capacity (more similar to ``boost::container::static_vector``). |
  76. | | | This container type is more efficient than other vector-like types because it makes |
  77. | | | no heap allocations. |
  78. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  79. | ``Span`` | ``std::span`` | Represents read-only access to a contiguous array without needing to copy any data. |
  80. | | | See `pull request description <https://github.com/godotengine/godot/pull/100293>`__ |
  81. | | | for details. |
  82. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  83. | ``HashSet`` | ``std::unordered_set`` | **Use this as the "default" set type.** |
  84. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  85. | ``RBSet`` | ``std::set`` | Uses a `red-black tree <https://en.wikipedia.org/wiki/Red-black_tree>`__ |
  86. | | | for faster access. |
  87. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  88. | ``VSet`` | ``std::flat_set`` | Uses copy-on-write (COW) semantics. |
  89. | | | This means it's generally slower but can be copied around almost for free. |
  90. | | | The performance benefits of ``VSet`` aren't established, so prefer using other types. |
  91. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  92. | ``HashMap`` | ``std::unordered_map`` | **Use this as the "default" map type.** Preserves insertion order. |
  93. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  94. | ``AHashMap`` | ``std::unordered_map`` | Array-based implementation of a hash map. Does not preserve insertion order. |
  95. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  96. | ``OAHashMap`` | ``std::unordered_map`` | Does not preserve insertion order. |
  97. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  98. | ``RBMap`` | ``std::map`` | Uses a `red-black tree <https://en.wikipedia.org/wiki/Red-black_tree>`__ |
  99. | | | for faster access. |
  100. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  101. | ``Dictionary`` 📜 | ``std::unordered_map`` | Keys and values can be of any Variant type. No static typing is imposed. |
  102. | | | Uses shared reference counting, similar to ``std::shared_ptr``. |
  103. | | | Preserves insertion order. Uses ``HashMap<Variant>`` internally. |
  104. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  105. | ``TypedDictionary`` 📜 | ``std::unordered_map`` | Subclass of ``Dictionary`` but with static typing for its keys and values. |
  106. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  107. | ``Pair`` | ``std::pair`` | Stores a single key-value pair. |
  108. +------------------------+--------------------------+---------------------------------------------------------------------------------------+
  109. ``auto`` keyword
  110. ~~~~~~~~~~~~~~~~
  111. Please don't use the ``auto`` keyword for type inference. While it can avoid
  112. repetition, it can also lead to confusing code:
  113. .. code-block:: cpp
  114. // Not so confusing...
  115. auto button = memnew(Button);
  116. // ...but what about this?
  117. auto result = EditorNode::get_singleton()->get_complex_result();
  118. Keep in mind hover documentation often isn't readily available for pull request
  119. reviewers. Most of the time, reviewers will use GitHub's online viewer to review
  120. pull requests.
  121. The ``auto`` keyword can be used in some special cases, like C++ lambda or Objective-C block
  122. definitions and C++ templates. Please ask before using templates with ``auto`` in a pull request.
  123. .. code-block:: cpp
  124. // Full type definitions.
  125. void (*mult64to128)(uint64_t, uint64_t, uint64_t &, uint64_t &) = [](uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) { ... }
  126. void (^JOYSTICK_LEFT)(GCControllerDirectionPad *__strong, float, float) = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) { ... }
  127. // Less clutter with auto.
  128. auto mult64to128 = [](uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) { ... }
  129. auto JOYSTICK_LEFT = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) { ... }
  130. // Compare function for different types.
  131. template <typename T1, typename T2>
  132. constexpr auto MIN(const T1 m_a, const T2 m_b) {
  133. return m_a < m_b ? m_a : m_b;
  134. }
  135. We chose to forbid ``auto`` in all other cases. Thank you for your understanding.
  136. Lambdas
  137. ~~~~~~~
  138. Lambdas should be used conservatively when they make code effectively faster or
  139. simpler, and do not impede readability. Please ask before using lambdas in a
  140. pull request.
  141. ``#ifdef``-based include guards
  142. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  143. Starting with 4.5, all files now use the ``#pragma once`` directive, as they
  144. improve readability and declutter macros. Use of ``#ifdef``-based include
  145. guards are now actively discouraged.
  146. ``try``-``catch`` blocks
  147. ~~~~~~~~~~~~~~~~~~~~~~~~
  148. C++ style exception handling using ``try`` and ``catch`` blocks is forbidden.
  149. This restriction is in place for several reasons, including performance, binary
  150. size and code complexity.
  151. Use :ref:`doc_common_engine_methods_and_macros_error_macros` instead.
  152. .. seealso::
  153. See :ref:`doc_code_style_guidelines_header_includes` for guidelines on sorting
  154. includes in C++ and Objective-C files.