🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
8.5 KiB

  1. # Frequently Asked Questions
  2. <!--
  3. @cond TURN_OFF_DOXYGEN
  4. -->
  5. # Table of Contents
  6. * [Introduction](#introduction)
  7. * [FAQ](#faq)
  8. * [Why is my debug build on Windows so slow?](#why-is-my-debug-build-on-windows-so-slow)
  9. * [How can I represent hierarchies with my components?](#how-can-i-represent-hierarchies-with-my-components)
  10. * [Custom entity identifiers: yay or nay?](#custom-entity-identifiers-yay-or-nay)
  11. * [Warning C4307: integral constant overflow](#warning-C4307-integral-constant-overflow)
  12. * [Warning C4003: the min, the max and the macro](#warning-C4003-the-min-the-max-and-the-macro)
  13. * [The standard and the non-copyable types](#the-standard-and-the-non-copyable-types)
  14. * [Which functions trigger which signals](#which-functions-trigger-which-signals)
  15. <!--
  16. @endcond TURN_OFF_DOXYGEN
  17. -->
  18. # Introduction
  19. This is a constantly updated section where I'll try to put the answers to the
  20. most frequently asked questions.<br/>
  21. If you don't find your answer here, there are two cases: nobody has done it yet
  22. or this section needs updating. In both cases, try to
  23. [open a new issue](https://github.com/skypjack/entt/issues/new) or enter the
  24. [gitter channel](https://gitter.im/skypjack/entt) and ask your question.
  25. Probably someone already has an answer for you and we can then integrate this
  26. part of the documentation.
  27. # FAQ
  28. ## Why is my debug build on Windows so slow?
  29. `EnTT` is an experimental project that I also use to keep me up-to-date with the
  30. latest revision of the language and the standard library. For this reason, it's
  31. likely that some classes you're working with are using standard containers under
  32. the hood.<br/>
  33. Unfortunately, it's known that the standard containers aren't particularly
  34. performing in debugging (the reasons for this go beyond this document) and are
  35. even less so on Windows apparently. Fortunately this can also be mitigated a
  36. lot, achieving good results in many cases.
  37. First of all, there are two things to do in a Windows project:
  38. * Disable the [`/JMC`](https://docs.microsoft.com/cpp/build/reference/jmc)
  39. option (_Just My Code_ debugging), available starting in Visual Studio 2017
  40. version 15.8.
  41. * Set the [`_ITERATOR_DEBUG_LEVEL`](https://docs.microsoft.com/cpp/standard-library/iterator-debug-level)
  42. macro to 0. This will disable checked iterators and iterator debugging.
  43. Moreover, the macro `ENTT_ASSERT` should be redefined to disable internal checks
  44. made by `EnTT` in debug:
  45. ```cpp
  46. #define ENTT_ASSERT(...) ((void)0)
  47. ```
  48. These asserts are introduced to help the users but they require to access to the
  49. underlying containers and therefore risk ruining the performance in some cases.
  50. With these changes, debug performance should increase enough for most cases. If
  51. you want something more, you can can also switch to an optimization level `O0`
  52. or preferably `O1`.
  53. ## How can I represent hierarchies with my components?
  54. This is one of the first questions that anyone makes when starting to work with
  55. the entity-component-system architectural pattern.<br/>
  56. There are several approaches to the problem and what’s the best one depends
  57. mainly on the real problem one is facing. In all cases, how to do it doesn't
  58. strictly depend on the library in use, but the latter can certainly allow or
  59. not different techniques depending on how the data are laid out.
  60. I tried to describe some of the techniques that fit well with the model of
  61. `EnTT`. [Here](https://skypjack.github.io/2019-06-25-ecs-baf-part-4/) is the
  62. first post of a series that tries to explore the problem. More will probably
  63. come in future.<br/>
  64. In addition, `EnTT` also offers the possibility to create stable storage types
  65. and therefore have pointer stability for one, all or some components. This is by
  66. far the most convenient solution when it comes to creating hierarchies and
  67. whatnot. See the documentation for the ECS part of the library and in particular
  68. what concerns the `component_traits` class for further details.
  69. ## Custom entity identifiers: yay or nay?
  70. Custom entity identifiers are definitely a good idea in two cases at least:
  71. * If `std::uint32_t` isn't large enough for your purposes, since this is the
  72. underlying type of `entt::entity`.
  73. * If you want to avoid conflicts when using multiple registries.
  74. Identifiers can be defined through enum classes and class types that define an
  75. `entity_type` member of type `std::uint32_t` or `std::uint64_t`.<br/>
  76. In fact, this is a definition equivalent to that of `entt::entity`:
  77. ```cpp
  78. enum class entity: std::uint32_t {};
  79. ```
  80. There is no limit to the number of identifiers that can be defined.
  81. ## Warning C4307: integral constant overflow
  82. According to [this](https://github.com/skypjack/entt/issues/121) issue, using a
  83. hashed string under VS could generate a warning.<br/>
  84. First of all, I want to reassure you: it's expected and harmless. However, it
  85. can be annoying.
  86. To suppress it and if you don't want to suppress all the other warnings as well,
  87. here is a workaround in the form of a macro:
  88. ```cpp
  89. #if defined(_MSC_VER)
  90. #define HS(str) __pragma(warning(suppress:4307)) entt::hashed_string{str}
  91. #else
  92. #define HS(str) entt::hashed_string{str}
  93. #endif
  94. ```
  95. With an example of use included:
  96. ```cpp
  97. constexpr auto identifier = HS("my/resource/identifier");
  98. ```
  99. Thanks to [huwpascoe](https://github.com/huwpascoe) for the courtesy.
  100. ## Warning C4003: the min, the max and the macro
  101. On Windows, a header file defines two macros `min` and `max` which may result in
  102. conflicts with their counterparts in the standard library and therefore in
  103. errors during compilation.
  104. It's a pretty big problem but fortunately it's not a problem of `EnTT` and there
  105. is a fairly simple solution to it.<br/>
  106. It consists in defining the `NOMINMAX` macro before to include any other header
  107. so as to get rid of the extra definitions:
  108. ```cpp
  109. #define NOMINMAX
  110. ```
  111. Please refer to [this](https://github.com/skypjack/entt/issues/96) issue for
  112. more details.
  113. ## The standard and the non-copyable types
  114. `EnTT` uses internally the trait `std::is_copy_constructible_v` to check if a
  115. component is actually copyable. However, this trait doesn't really check whether
  116. a type is actually copyable. Instead, it just checks that a suitable copy
  117. constructor and copy operator exist.<br/>
  118. This can lead to surprising results due to some idiosyncrasies of the standard.
  119. For example, `std::vector` defines a copy constructor that is conditionally
  120. enabled depending on whether the value type is copyable or not. As a result,
  121. `std::is_copy_constructible_v` returns true for the following specialization:
  122. ```cpp
  123. struct type {
  124. std::vector<std::unique_ptr<action>> vec;
  125. };
  126. ```
  127. However, the copy constructor is effectively disabled upon specialization.
  128. Therefore, trying to assign an instance of this type to an entity may trigger a
  129. compilation error.<br/>
  130. As a workaround, users can mark the type explicitly as non-copyable. This also
  131. suppresses the implicit generation of the move constructor and operator, which
  132. will therefore have to be defaulted accordingly:
  133. ```cpp
  134. struct type {
  135. type(const type &) = delete;
  136. type(type &&) = default;
  137. type & operator=(const type &) = delete;
  138. type & operator=(type &&) = default;
  139. std::vector<std::unique_ptr<action>> vec;
  140. };
  141. ```
  142. Note that aggregate initialization is also disabled as a consequence.<br/>
  143. Fortunately, this type of trick is quite rare. The bad news is that there is no
  144. way to deal with it at the library level, this being due to the design of the
  145. language. On the other hand, the fact that the language itself also offers a way
  146. to mitigate the problem makes it manageable.
  147. ## Which functions trigger which signals
  148. The `registry` class offers three signals that are emitted following specific
  149. operations. Maybe not everyone knows what these operations are, though.<br/>
  150. If this isn't clear, below you can find a _vademecum_ for this purpose:
  151. * `on_created` is invoked when a component is first added (neither modified nor
  152. replaced) to an entity.
  153. * `on_update` is called whenever an existing component is modified or replaced.
  154. * `on_destroyed` is called when a component is explicitly or implicitly removed
  155. from an entity.
  156. Among the most controversial functions can be found `emplace_or_replace` and
  157. `destroy`. However, following the above rules, it's quite simple to know what
  158. will happen.<br/>
  159. In the first case, `on_created` is invoked if the entity has not the component,
  160. otherwise the latter is replaced and therefore `on_update` is triggered. As for
  161. the second case, components are removed from their entities and thus freed when
  162. they are recycled. It means that `on_destroyed` is triggered for every component
  163. owned by the entity that is destroyed.