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

651 lines
20 KiB

  1. #ifndef ENTT_CORE_TYPE_TRAITS_HPP
  2. #define ENTT_CORE_TYPE_TRAITS_HPP
  3. #include <cstddef>
  4. #include <iterator>
  5. #include <type_traits>
  6. #include <utility>
  7. #include "../config/config.h"
  8. #include "fwd.hpp"
  9. namespace entt {
  10. /**
  11. * @brief Utility class to disambiguate overloaded functions.
  12. * @tparam N Number of choices available.
  13. */
  14. template<std::size_t N>
  15. struct choice_t
  16. // Unfortunately, doxygen cannot parse such a construct.
  17. : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
  18. {};
  19. /*! @copybrief choice_t */
  20. template<>
  21. struct choice_t<0> {};
  22. /**
  23. * @brief Variable template for the choice trick.
  24. * @tparam N Number of choices available.
  25. */
  26. template<std::size_t N>
  27. inline constexpr choice_t<N> choice{};
  28. /**
  29. * @brief Identity type trait.
  30. *
  31. * Useful to establish non-deduced contexts in template argument deduction
  32. * (waiting for C++20) or to provide types through function arguments.
  33. *
  34. * @tparam Type A type.
  35. */
  36. template<typename Type>
  37. struct type_identity {
  38. /*! @brief Identity type. */
  39. using type = Type;
  40. };
  41. /**
  42. * @brief Helper type.
  43. * @tparam Type A type.
  44. */
  45. template<typename Type>
  46. using type_identity_t = typename type_identity<Type>::type;
  47. /**
  48. * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
  49. * @tparam Type The type of which to return the size.
  50. * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
  51. */
  52. template<typename Type, typename = void>
  53. struct size_of: std::integral_constant<std::size_t, 0u> {};
  54. /*! @copydoc size_of */
  55. template<typename Type>
  56. struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
  57. : std::integral_constant<std::size_t, sizeof(Type)> {};
  58. /**
  59. * @brief Helper variable template.
  60. * @tparam Type The type of which to return the size.
  61. */
  62. template<typename Type>
  63. inline constexpr std::size_t size_of_v = size_of<Type>::value;
  64. /**
  65. * @brief Using declaration to be used to _repeat_ the same type a number of
  66. * times equal to the size of a given parameter pack.
  67. * @tparam Type A type to repeat.
  68. */
  69. template<typename Type, typename>
  70. using unpack_as_type = Type;
  71. /**
  72. * @brief Helper variable template to be used to _repeat_ the same value a
  73. * number of times equal to the size of a given parameter pack.
  74. * @tparam Value A value to repeat.
  75. */
  76. template<auto Value, typename>
  77. inline constexpr auto unpack_as_value = Value;
  78. /**
  79. * @brief Wraps a static constant.
  80. * @tparam Value A static constant.
  81. */
  82. template<auto Value>
  83. using integral_constant = std::integral_constant<decltype(Value), Value>;
  84. /**
  85. * @brief Alias template to facilitate the creation of named values.
  86. * @tparam Value A constant value at least convertible to `id_type`.
  87. */
  88. template<id_type Value>
  89. using tag = integral_constant<Value>;
  90. /**
  91. * @brief A class to use to push around lists of types, nothing more.
  92. * @tparam Type Types provided by the type list.
  93. */
  94. template<typename... Type>
  95. struct type_list {
  96. /*! @brief Type list type. */
  97. using type = type_list;
  98. /*! @brief Compile-time number of elements in the type list. */
  99. static constexpr auto size = sizeof...(Type);
  100. };
  101. /*! @brief Primary template isn't defined on purpose. */
  102. template<std::size_t, typename>
  103. struct type_list_element;
  104. /**
  105. * @brief Provides compile-time indexed access to the types of a type list.
  106. * @tparam Index Index of the type to return.
  107. * @tparam Type First type provided by the type list.
  108. * @tparam Other Other types provided by the type list.
  109. */
  110. template<std::size_t Index, typename Type, typename... Other>
  111. struct type_list_element<Index, type_list<Type, Other...>>
  112. : type_list_element<Index - 1u, type_list<Other...>> {};
  113. /**
  114. * @brief Provides compile-time indexed access to the types of a type list.
  115. * @tparam Type First type provided by the type list.
  116. * @tparam Other Other types provided by the type list.
  117. */
  118. template<typename Type, typename... Other>
  119. struct type_list_element<0u, type_list<Type, Other...>> {
  120. /*! @brief Searched type. */
  121. using type = Type;
  122. };
  123. /**
  124. * @brief Helper type.
  125. * @tparam Index Index of the type to return.
  126. * @tparam List Type list to search into.
  127. */
  128. template<std::size_t Index, typename List>
  129. using type_list_element_t = typename type_list_element<Index, List>::type;
  130. /**
  131. * @brief Concatenates multiple type lists.
  132. * @tparam Type Types provided by the first type list.
  133. * @tparam Other Types provided by the second type list.
  134. * @return A type list composed by the types of both the type lists.
  135. */
  136. template<typename... Type, typename... Other>
  137. constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
  138. return {};
  139. }
  140. /*! @brief Primary template isn't defined on purpose. */
  141. template<typename...>
  142. struct type_list_cat;
  143. /*! @brief Concatenates multiple type lists. */
  144. template<>
  145. struct type_list_cat<> {
  146. /*! @brief A type list composed by the types of all the type lists. */
  147. using type = type_list<>;
  148. };
  149. /**
  150. * @brief Concatenates multiple type lists.
  151. * @tparam Type Types provided by the first type list.
  152. * @tparam Other Types provided by the second type list.
  153. * @tparam List Other type lists, if any.
  154. */
  155. template<typename... Type, typename... Other, typename... List>
  156. struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
  157. /*! @brief A type list composed by the types of all the type lists. */
  158. using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
  159. };
  160. /**
  161. * @brief Concatenates multiple type lists.
  162. * @tparam Type Types provided by the type list.
  163. */
  164. template<typename... Type>
  165. struct type_list_cat<type_list<Type...>> {
  166. /*! @brief A type list composed by the types of all the type lists. */
  167. using type = type_list<Type...>;
  168. };
  169. /**
  170. * @brief Helper type.
  171. * @tparam List Type lists to concatenate.
  172. */
  173. template<typename... List>
  174. using type_list_cat_t = typename type_list_cat<List...>::type;
  175. /*! @brief Primary template isn't defined on purpose. */
  176. template<typename>
  177. struct type_list_unique;
  178. /**
  179. * @brief Removes duplicates types from a type list.
  180. * @tparam Type One of the types provided by the given type list.
  181. * @tparam Other The other types provided by the given type list.
  182. */
  183. template<typename Type, typename... Other>
  184. struct type_list_unique<type_list<Type, Other...>> {
  185. /*! @brief A type list without duplicate types. */
  186. using type = std::conditional_t<
  187. (std::is_same_v<Type, Other> || ...),
  188. typename type_list_unique<type_list<Other...>>::type,
  189. type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
  190. };
  191. /*! @brief Removes duplicates types from a type list. */
  192. template<>
  193. struct type_list_unique<type_list<>> {
  194. /*! @brief A type list without duplicate types. */
  195. using type = type_list<>;
  196. };
  197. /**
  198. * @brief Helper type.
  199. * @tparam Type A type list.
  200. */
  201. template<typename Type>
  202. using type_list_unique_t = typename type_list_unique<Type>::type;
  203. /**
  204. * @brief Provides the member constant `value` to true if a type list contains a
  205. * given type, false otherwise.
  206. * @tparam List Type list.
  207. * @tparam Type Type to look for.
  208. */
  209. template<typename List, typename Type>
  210. struct type_list_contains;
  211. /**
  212. * @copybrief type_list_contains
  213. * @tparam Type Types provided by the type list.
  214. * @tparam Other Type to look for.
  215. */
  216. template<typename... Type, typename Other>
  217. struct type_list_contains<type_list<Type...>, Other>: std::disjunction<std::is_same<Type, Other>...> {};
  218. /**
  219. * @brief Helper variable template.
  220. * @tparam List Type list.
  221. * @tparam Type Type to look for.
  222. */
  223. template<typename List, typename Type>
  224. inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
  225. /*! @brief Primary template isn't defined on purpose. */
  226. template<typename...>
  227. struct type_list_diff;
  228. /**
  229. * @brief Computes the difference between two type lists.
  230. * @tparam Type Types provided by the first type list.
  231. * @tparam Other Types provided by the second type list.
  232. */
  233. template<typename... Type, typename... Other>
  234. struct type_list_diff<type_list<Type...>, type_list<Other...>> {
  235. /*! @brief A type list that is the difference between the two type lists. */
  236. using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
  237. };
  238. /**
  239. * @brief Helper type.
  240. * @tparam List Type lists between which to compute the difference.
  241. */
  242. template<typename... List>
  243. using type_list_diff_t = typename type_list_diff<List...>::type;
  244. /**
  245. * @brief A class to use to push around lists of constant values, nothing more.
  246. * @tparam Value Values provided by the value list.
  247. */
  248. template<auto... Value>
  249. struct value_list {
  250. /*! @brief Value list type. */
  251. using type = value_list;
  252. /*! @brief Compile-time number of elements in the value list. */
  253. static constexpr auto size = sizeof...(Value);
  254. };
  255. /*! @brief Primary template isn't defined on purpose. */
  256. template<std::size_t, typename>
  257. struct value_list_element;
  258. /**
  259. * @brief Provides compile-time indexed access to the values of a value list.
  260. * @tparam Index Index of the value to return.
  261. * @tparam Value First value provided by the value list.
  262. * @tparam Other Other values provided by the value list.
  263. */
  264. template<std::size_t Index, auto Value, auto... Other>
  265. struct value_list_element<Index, value_list<Value, Other...>>
  266. : value_list_element<Index - 1u, value_list<Other...>> {};
  267. /**
  268. * @brief Provides compile-time indexed access to the types of a type list.
  269. * @tparam Value First value provided by the value list.
  270. * @tparam Other Other values provided by the value list.
  271. */
  272. template<auto Value, auto... Other>
  273. struct value_list_element<0u, value_list<Value, Other...>> {
  274. /*! @brief Searched value. */
  275. static constexpr auto value = Value;
  276. };
  277. /**
  278. * @brief Helper type.
  279. * @tparam Index Index of the value to return.
  280. * @tparam List Value list to search into.
  281. */
  282. template<std::size_t Index, typename List>
  283. inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
  284. /**
  285. * @brief Concatenates multiple value lists.
  286. * @tparam Value Values provided by the first value list.
  287. * @tparam Other Values provided by the second value list.
  288. * @return A value list composed by the values of both the value lists.
  289. */
  290. template<auto... Value, auto... Other>
  291. constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
  292. return {};
  293. }
  294. /*! @brief Primary template isn't defined on purpose. */
  295. template<typename...>
  296. struct value_list_cat;
  297. /*! @brief Concatenates multiple value lists. */
  298. template<>
  299. struct value_list_cat<> {
  300. /*! @brief A value list composed by the values of all the value lists. */
  301. using type = value_list<>;
  302. };
  303. /**
  304. * @brief Concatenates multiple value lists.
  305. * @tparam Value Values provided by the first value list.
  306. * @tparam Other Values provided by the second value list.
  307. * @tparam List Other value lists, if any.
  308. */
  309. template<auto... Value, auto... Other, typename... List>
  310. struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
  311. /*! @brief A value list composed by the values of all the value lists. */
  312. using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
  313. };
  314. /**
  315. * @brief Concatenates multiple value lists.
  316. * @tparam Value Values provided by the value list.
  317. */
  318. template<auto... Value>
  319. struct value_list_cat<value_list<Value...>> {
  320. /*! @brief A value list composed by the values of all the value lists. */
  321. using type = value_list<Value...>;
  322. };
  323. /**
  324. * @brief Helper type.
  325. * @tparam List Value lists to concatenate.
  326. */
  327. template<typename... List>
  328. using value_list_cat_t = typename value_list_cat<List...>::type;
  329. /*! @brief Same as std::is_invocable, but with tuples. */
  330. template<typename, typename>
  331. struct is_applicable: std::false_type {};
  332. /**
  333. * @copybrief is_applicable
  334. * @tparam Func A valid function type.
  335. * @tparam Tuple Tuple-like type.
  336. * @tparam Args The list of arguments to use to probe the function type.
  337. */
  338. template<typename Func, template<typename...> class Tuple, typename... Args>
  339. struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
  340. /**
  341. * @copybrief is_applicable
  342. * @tparam Func A valid function type.
  343. * @tparam Tuple Tuple-like type.
  344. * @tparam Args The list of arguments to use to probe the function type.
  345. */
  346. template<typename Func, template<typename...> class Tuple, typename... Args>
  347. struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
  348. /**
  349. * @brief Helper variable template.
  350. * @tparam Func A valid function type.
  351. * @tparam Args The list of arguments to use to probe the function type.
  352. */
  353. template<typename Func, typename Args>
  354. inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
  355. /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
  356. template<typename, typename, typename>
  357. struct is_applicable_r: std::false_type {};
  358. /**
  359. * @copybrief is_applicable_r
  360. * @tparam Ret The type to which the return type of the function should be
  361. * convertible.
  362. * @tparam Func A valid function type.
  363. * @tparam Args The list of arguments to use to probe the function type.
  364. */
  365. template<typename Ret, typename Func, typename... Args>
  366. struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
  367. /**
  368. * @brief Helper variable template.
  369. * @tparam Ret The type to which the return type of the function should be
  370. * convertible.
  371. * @tparam Func A valid function type.
  372. * @tparam Args The list of arguments to use to probe the function type.
  373. */
  374. template<typename Ret, typename Func, typename Args>
  375. inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
  376. /**
  377. * @brief Provides the member constant `value` to true if a given type is
  378. * complete, false otherwise.
  379. * @tparam Type The type to test.
  380. */
  381. template<typename Type, typename = void>
  382. struct is_complete: std::false_type {};
  383. /*! @copydoc is_complete */
  384. template<typename Type>
  385. struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
  386. /**
  387. * @brief Helper variable template.
  388. * @tparam Type The type to test.
  389. */
  390. template<typename Type>
  391. inline constexpr bool is_complete_v = is_complete<Type>::value;
  392. /**
  393. * @brief Provides the member constant `value` to true if a given type is an
  394. * iterator, false otherwise.
  395. * @tparam Type The type to test.
  396. */
  397. template<typename Type, typename = void>
  398. struct is_iterator: std::false_type {};
  399. /**
  400. * @cond TURN_OFF_DOXYGEN
  401. * Internal details not to be documented.
  402. */
  403. namespace internal {
  404. template<typename, typename = void>
  405. struct has_iterator_category: std::false_type {};
  406. template<typename Type>
  407. struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
  408. } // namespace internal
  409. /**
  410. * Internal details not to be documented.
  411. * @endcond
  412. */
  413. /*! @copydoc is_iterator */
  414. template<typename Type>
  415. struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_pointer_t<Type>>, void>>>
  416. : internal::has_iterator_category<Type> {};
  417. /**
  418. * @brief Helper variable template.
  419. * @tparam Type The type to test.
  420. */
  421. template<typename Type>
  422. inline constexpr bool is_iterator_v = is_iterator<Type>::value;
  423. /**
  424. * @brief Provides the member constant `value` to true if a given type is both
  425. * an empty and non-final class, false otherwise.
  426. * @tparam Type The type to test
  427. */
  428. template<typename Type>
  429. struct is_ebco_eligible
  430. : std::conjunction<std::is_empty<Type>, std::negation<std::is_final<Type>>> {};
  431. /**
  432. * @brief Helper variable template.
  433. * @tparam Type The type to test.
  434. */
  435. template<typename Type>
  436. inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
  437. /**
  438. * @brief Provides the member constant `value` to true if `Type::is_transparent`
  439. * is valid and denotes a type, false otherwise.
  440. * @tparam Type The type to test.
  441. */
  442. template<typename Type, typename = void>
  443. struct is_transparent: std::false_type {};
  444. /*! @copydoc is_transparent */
  445. template<typename Type>
  446. struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
  447. /**
  448. * @brief Helper variable template.
  449. * @tparam Type The type to test.
  450. */
  451. template<typename Type>
  452. inline constexpr bool is_transparent_v = is_transparent<Type>::value;
  453. /**
  454. * @brief Provides the member constant `value` to true if a given type is
  455. * equality comparable, false otherwise.
  456. * @tparam Type The type to test.
  457. */
  458. template<typename Type, typename = void>
  459. struct is_equality_comparable: std::false_type {};
  460. /**
  461. * @cond TURN_OFF_DOXYGEN
  462. * Internal details not to be documented.
  463. */
  464. namespace internal {
  465. template<typename, typename = void>
  466. struct has_tuple_size_value: std::false_type {};
  467. template<typename Type>
  468. struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
  469. template<typename Type, std::size_t... Index>
  470. [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
  471. return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
  472. }
  473. template<typename>
  474. [[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
  475. return true;
  476. }
  477. template<typename Type>
  478. [[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
  479. if constexpr(is_iterator_v<Type>) {
  480. return true;
  481. } else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
  482. return maybe_equality_comparable<Type>(choice<0>);
  483. } else {
  484. return is_equality_comparable<typename Type::value_type>::value;
  485. }
  486. }
  487. template<typename Type>
  488. [[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_const_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
  489. if constexpr(has_tuple_size_value<Type>::value) {
  490. return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
  491. } else {
  492. return maybe_equality_comparable<Type>(choice<1>);
  493. }
  494. }
  495. } // namespace internal
  496. /**
  497. * Internal details not to be documented.
  498. * @endcond
  499. */
  500. /*! @copydoc is_equality_comparable */
  501. template<typename Type>
  502. struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
  503. : std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
  504. /**
  505. * @brief Helper variable template.
  506. * @tparam Type The type to test.
  507. */
  508. template<typename Type>
  509. inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
  510. /**
  511. * @brief Transcribes the constness of a type to another type.
  512. * @tparam To The type to which to transcribe the constness.
  513. * @tparam From The type from which to transcribe the constness.
  514. */
  515. template<typename To, typename From>
  516. struct constness_as {
  517. /*! @brief The type resulting from the transcription of the constness. */
  518. using type = std::remove_const_t<To>;
  519. };
  520. /*! @copydoc constness_as */
  521. template<typename To, typename From>
  522. struct constness_as<To, const From> {
  523. /*! @brief The type resulting from the transcription of the constness. */
  524. using type = std::add_const_t<To>;
  525. };
  526. /**
  527. * @brief Alias template to facilitate the transcription of the constness.
  528. * @tparam To The type to which to transcribe the constness.
  529. * @tparam From The type from which to transcribe the constness.
  530. */
  531. template<typename To, typename From>
  532. using constness_as_t = typename constness_as<To, From>::type;
  533. /**
  534. * @brief Extracts the class of a non-static member object or function.
  535. * @tparam Member A pointer to a non-static member object or function.
  536. */
  537. template<typename Member>
  538. class member_class {
  539. static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
  540. template<typename Class, typename Ret, typename... Args>
  541. static Class *clazz(Ret (Class::*)(Args...));
  542. template<typename Class, typename Ret, typename... Args>
  543. static Class *clazz(Ret (Class::*)(Args...) const);
  544. template<typename Class, typename Type>
  545. static Class *clazz(Type Class::*);
  546. public:
  547. /*! @brief The class of the given non-static member object or function. */
  548. using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
  549. };
  550. /**
  551. * @brief Helper type.
  552. * @tparam Member A pointer to a non-static member object or function.
  553. */
  554. template<typename Member>
  555. using member_class_t = typename member_class<Member>::type;
  556. } // namespace entt
  557. #endif