🛠️🐜 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.

274 lines
8.0 KiB

  1. #ifndef ENTT_CORE_TYPE_INFO_HPP
  2. #define ENTT_CORE_TYPE_INFO_HPP
  3. #include <string_view>
  4. #include <type_traits>
  5. #include <utility>
  6. #include "../config/config.h"
  7. #include "../core/attribute.h"
  8. #include "fwd.hpp"
  9. #include "hashed_string.hpp"
  10. namespace entt {
  11. /**
  12. * @cond TURN_OFF_DOXYGEN
  13. * Internal details not to be documented.
  14. */
  15. namespace internal {
  16. struct ENTT_API type_index final {
  17. [[nodiscard]] static id_type next() ENTT_NOEXCEPT {
  18. static ENTT_MAYBE_ATOMIC(id_type) value{};
  19. return value++;
  20. }
  21. };
  22. template<typename Type>
  23. [[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
  24. #if defined ENTT_PRETTY_FUNCTION
  25. std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
  26. auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
  27. auto value = pretty_function.substr(first, pretty_function.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
  28. return value;
  29. #else
  30. return std::string_view{""};
  31. #endif
  32. }
  33. template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
  34. [[nodiscard]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
  35. constexpr auto value = stripped_type_name<Type>();
  36. return value;
  37. }
  38. template<typename Type>
  39. [[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
  40. static const auto value = stripped_type_name<Type>();
  41. return value;
  42. }
  43. template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
  44. [[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
  45. constexpr auto stripped = stripped_type_name<Type>();
  46. constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
  47. return value;
  48. }
  49. template<typename Type>
  50. [[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
  51. static const auto value = [](const auto stripped) {
  52. return hashed_string::value(stripped.data(), stripped.size());
  53. }(stripped_type_name<Type>());
  54. return value;
  55. }
  56. } // namespace internal
  57. /**
  58. * Internal details not to be documented.
  59. * @endcond
  60. */
  61. /**
  62. * @brief Type sequential identifier.
  63. * @tparam Type Type for which to generate a sequential identifier.
  64. */
  65. template<typename Type, typename = void>
  66. struct ENTT_API type_index final {
  67. /**
  68. * @brief Returns the sequential identifier of a given type.
  69. * @return The sequential identifier of a given type.
  70. */
  71. [[nodiscard]] static id_type value() ENTT_NOEXCEPT {
  72. static const id_type value = internal::type_index::next();
  73. return value;
  74. }
  75. /*! @copydoc value */
  76. [[nodiscard]] constexpr operator id_type() const ENTT_NOEXCEPT {
  77. return value();
  78. }
  79. };
  80. /**
  81. * @brief Type hash.
  82. * @tparam Type Type for which to generate a hash value.
  83. */
  84. template<typename Type, typename = void>
  85. struct type_hash final {
  86. /**
  87. * @brief Returns the numeric representation of a given type.
  88. * @return The numeric representation of the given type.
  89. */
  90. #if defined ENTT_PRETTY_FUNCTION
  91. [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
  92. return internal::type_hash<Type>(0);
  93. #else
  94. [[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
  95. return type_index<Type>::value();
  96. #endif
  97. }
  98. /*! @copydoc value */
  99. [[nodiscard]] constexpr operator id_type() const ENTT_NOEXCEPT {
  100. return value();
  101. }
  102. };
  103. /**
  104. * @brief Type name.
  105. * @tparam Type Type for which to generate a name.
  106. */
  107. template<typename Type, typename = void>
  108. struct type_name final {
  109. /**
  110. * @brief Returns the name of a given type.
  111. * @return The name of the given type.
  112. */
  113. [[nodiscard]] static constexpr std::string_view value() ENTT_NOEXCEPT {
  114. return internal::type_name<Type>(0);
  115. }
  116. /*! @copydoc value */
  117. [[nodiscard]] constexpr operator std::string_view() const ENTT_NOEXCEPT {
  118. return value();
  119. }
  120. };
  121. /*! @brief Implementation specific information about a type. */
  122. struct type_info final {
  123. /**
  124. * @brief Constructs a type info object for a given type.
  125. * @tparam Type Type for which to construct a type info object.
  126. */
  127. template<typename Type>
  128. constexpr type_info(std::in_place_type_t<Type>) ENTT_NOEXCEPT
  129. : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
  130. identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
  131. alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
  132. /**
  133. * @brief Type index.
  134. * @return Type index.
  135. */
  136. [[nodiscard]] constexpr id_type index() const ENTT_NOEXCEPT {
  137. return seq;
  138. }
  139. /**
  140. * @brief Type hash.
  141. * @return Type hash.
  142. */
  143. [[nodiscard]] constexpr id_type hash() const ENTT_NOEXCEPT {
  144. return identifier;
  145. }
  146. /**
  147. * @brief Type name.
  148. * @return Type name.
  149. */
  150. [[nodiscard]] constexpr std::string_view name() const ENTT_NOEXCEPT {
  151. return alias;
  152. }
  153. private:
  154. id_type seq;
  155. id_type identifier;
  156. std::string_view alias;
  157. };
  158. /**
  159. * @brief Compares the contents of two type info objects.
  160. * @param lhs A type info object.
  161. * @param rhs A type info object.
  162. * @return True if the two type info objects are identical, false otherwise.
  163. */
  164. [[nodiscard]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
  165. return lhs.hash() == rhs.hash();
  166. }
  167. /**
  168. * @brief Compares the contents of two type info objects.
  169. * @param lhs A type info object.
  170. * @param rhs A type info object.
  171. * @return True if the two type info objects differ, false otherwise.
  172. */
  173. [[nodiscard]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
  174. return !(lhs == rhs);
  175. }
  176. /**
  177. * @brief Compares two type info objects.
  178. * @param lhs A valid type info object.
  179. * @param rhs A valid type info object.
  180. * @return True if the first element is less than the second, false otherwise.
  181. */
  182. [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
  183. return lhs.index() < rhs.index();
  184. }
  185. /**
  186. * @brief Compares two type info objects.
  187. * @param lhs A valid type info object.
  188. * @param rhs A valid type info object.
  189. * @return True if the first element is less than or equal to the second, false
  190. * otherwise.
  191. */
  192. [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
  193. return !(rhs < lhs);
  194. }
  195. /**
  196. * @brief Compares two type info objects.
  197. * @param lhs A valid type info object.
  198. * @param rhs A valid type info object.
  199. * @return True if the first element is greater than the second, false
  200. * otherwise.
  201. */
  202. [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
  203. return rhs < lhs;
  204. }
  205. /**
  206. * @brief Compares two type info objects.
  207. * @param lhs A valid type info object.
  208. * @param rhs A valid type info object.
  209. * @return True if the first element is greater than or equal to the second,
  210. * false otherwise.
  211. */
  212. [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
  213. return !(lhs < rhs);
  214. }
  215. /**
  216. * @brief Returns the type info object associated to a given type.
  217. *
  218. * The returned element refers to an object with static storage duration.<br/>
  219. * The type doesn't need to be a complete type. If the type is a reference, the
  220. * result refers to the referenced type. In all cases, top-level cv-qualifiers
  221. * are ignored.
  222. *
  223. * @tparam Type Type for which to generate a type info object.
  224. * @return A reference to a properly initialized type info object.
  225. */
  226. template<typename Type>
  227. [[nodiscard]] const type_info &type_id() ENTT_NOEXCEPT {
  228. if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
  229. static type_info instance{std::in_place_type<Type>};
  230. return instance;
  231. } else {
  232. return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
  233. }
  234. }
  235. /*! @copydoc type_id */
  236. template<typename Type>
  237. [[nodiscard]] const type_info &type_id(Type &&) ENTT_NOEXCEPT {
  238. return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
  239. }
  240. } // namespace entt
  241. #endif