utility.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /************************************************************************************
  2. * *
  3. * Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org> *
  4. * *
  5. * This file is part of RTTR (Run Time Type Reflection) *
  6. * License: MIT License *
  7. * *
  8. * Permission is hereby granted, free of charge, to any person obtaining *
  9. * a copy of this software and associated documentation files (the "Software"), *
  10. * to deal in the Software without restriction, including without limitation *
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  12. * and/or sell copies of the Software, and to permit persons to whom the *
  13. * Software is furnished to do so, subject to the following conditions: *
  14. * *
  15. * The above copyright notice and this permission notice shall be included in *
  16. * all copies or substantial portions of the Software. *
  17. * *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
  24. * SOFTWARE. *
  25. * *
  26. *************************************************************************************/
  27. #ifndef RTTR_UTILITY_H_
  28. #define RTTR_UTILITY_H_
  29. #include "rttr/detail/base/core_prerequisites.h"
  30. #include "rttr/detail/misc/std_type_traits.h"
  31. #include "rttr/detail/misc/misc_type_traits.h"
  32. #include <cstddef>
  33. #include <memory>
  34. #include <type_traits>
  35. #include <utility>
  36. #include <algorithm>
  37. #include <string>
  38. #ifdef RTTR_NO_CXX17_NOEXCEPT_FUNC_TYPE
  39. RTTR_BEGIN_DISABLE_EXCEPT_TYPE_WARNING
  40. #endif
  41. namespace rttr
  42. {
  43. namespace detail
  44. {
  45. /////////////////////////////////////////////////////////////////////////////////////////
  46. /////////////////////////////////////////////////////////////////////////////////////////
  47. // This will add the c++14 integer sequence to c++11
  48. template <class T, T... I>
  49. struct integer_sequence
  50. {
  51. template <T N> using append = integer_sequence<T, I..., N>;
  52. static std::size_t size() { return sizeof...(I); }
  53. using next = append<sizeof...(I)>;
  54. using type = T;
  55. };
  56. template <class T, T Index, std::size_t N>
  57. struct sequence_generator
  58. {
  59. using type = typename sequence_generator<T, Index - 1, N - 1>::type::next;
  60. };
  61. template <class T, T Index>
  62. struct sequence_generator<T, Index, 0ul> { using type = integer_sequence<T>; };
  63. template <std::size_t... I>
  64. using index_sequence = integer_sequence<std::size_t, I...>;
  65. template <class T, T N>
  66. using make_integer_sequence = typename sequence_generator<T, N, N>::type;
  67. template <std::size_t N>
  68. using make_index_sequence = make_integer_sequence<std::size_t, N>;
  69. template<class... T>
  70. using index_sequence_for = make_index_sequence<sizeof...(T)>;
  71. /////////////////////////////////////////////////////////////////////////////////////////
  72. /////////////////////////////////////////////////////////////////////////////////////////
  73. /////////////////////////////////////////////////////////////////////////////////////////
  74. // will remove all numbers of the given index sequence till the given \p Index.
  75. // typename erase_sequence_till<index_sequence<0, 1, 2, 3, 4>, 3>::type => index_sequence<3, 4>
  76. template<typename Index_Sequence, std::size_t Index>
  77. struct erase_sequence_till;
  78. template<std::size_t Index, std::size_t Idx, std::size_t... I>
  79. struct erase_sequence_till<index_sequence<Idx, I...>, Index>
  80. {
  81. using type = conditional_t< Idx == Index,
  82. index_sequence<Idx, I...>,
  83. typename erase_sequence_till<index_sequence<I...>, Index>::type>;
  84. };
  85. template<std::size_t Index>
  86. struct erase_sequence_till<index_sequence<>, Index>
  87. {
  88. using type = index_sequence<>;
  89. };
  90. /////////////////////////////////////////////////////////////////////////////////////////
  91. /////////////////////////////////////////////////////////////////////////////////////////
  92. /////////////////////////////////////////////////////////////////////////////////////////
  93. template<typename T>
  94. struct remove_first_index_impl
  95. {
  96. using type = index_sequence<>;
  97. };
  98. template<std::size_t First, std::size_t... I>
  99. struct remove_first_index_impl<detail::index_sequence<First, I...>>
  100. {
  101. using type = detail::index_sequence<I...>;
  102. };
  103. template<typename T>
  104. using remove_first_index = typename remove_first_index_impl<T>::type;
  105. /////////////////////////////////////////////////////////////////////////////////////////
  106. template<typename, typename>
  107. struct concat_index_sequence { };
  108. template<std::size_t... Ts, std::size_t... Us>
  109. struct concat_index_sequence<index_sequence<Ts...>, index_sequence<Us...>>
  110. {
  111. using type = index_sequence<Ts..., Us...>;
  112. };
  113. /////////////////////////////////////////////////////////////////////////////////////////
  114. template <class T>
  115. struct remove_last_index_impl;
  116. template <size_t Last>
  117. struct remove_last_index_impl<index_sequence<Last>>
  118. {
  119. using type = index_sequence<>;
  120. };
  121. template<std::size_t First, std::size_t... I>
  122. struct remove_last_index_impl<index_sequence<First, I...>>
  123. {
  124. using type = typename concat_index_sequence<
  125. index_sequence<First>,
  126. typename remove_last_index_impl<index_sequence<I...>>::type
  127. >::type;
  128. };
  129. template<typename T>
  130. using remove_last_index = typename remove_last_index_impl<T>::type;
  131. /////////////////////////////////////////////////////////////////////////////////////////
  132. /////////////////////////////////////////////////////////////////////////////////////////
  133. //template<typename T, std::size_t Index>
  134. //using type_identity = T;
  135. //
  136. template<typename T, std::size_t Index>
  137. struct type_identity
  138. {
  139. using type = T;
  140. };
  141. template<typename T, std::size_t N, typename Indices = make_index_sequence<N>>
  142. struct create_type_list;
  143. template<typename T, std::size_t N, std::size_t... Indices>
  144. struct create_type_list<T, N, index_sequence<Indices...>>
  145. {
  146. using type = type_list<typename type_identity<T, Indices>::type...>;
  147. };
  148. // creates a type list with type T, N times in it
  149. // e.g. create_type_list_t<int, 3> => type_list<int, int, int>
  150. template<typename T, std::size_t N>
  151. using create_type_list_t = typename create_type_list<T, N>::type;
  152. /////////////////////////////////////////////////////////////////////////////////////////
  153. /////////////////////////////////////////////////////////////////////////////////////////
  154. static RTTR_FORCE_INLINE bool check_all_true() { return true; }
  155. template<typename... BoolArgs>
  156. static RTTR_INLINE bool check_all_true(bool arg1, BoolArgs... args) { return arg1 & check_all_true(args...); }
  157. /////////////////////////////////////////////////////////////////////////////////////////
  158. /////////////////////////////////////////////////////////////////////////////////////////
  159. // copy the content of any arbitrary array, use it like:
  160. // copy_array(in, out);
  161. // works with every dimension
  162. template<typename ElementType>
  163. struct copy_array_impl
  164. {
  165. void operator()(const ElementType &in, ElementType &out)
  166. {
  167. out = in;
  168. }
  169. };
  170. template<typename ElementType, std::size_t Count>
  171. struct copy_array_impl<ElementType[Count]>
  172. {
  173. void operator()(const ElementType (&in)[Count], ElementType (&out)[Count])
  174. {
  175. for(std::size_t i = 0; i < Count; ++i)
  176. copy_array_impl<ElementType>()(in[i], out[i]);
  177. }
  178. };
  179. template<typename ElementType, std::size_t Count>
  180. auto copy_array(const ElementType (&in)[Count], ElementType (&out)[Count])
  181. -> ElementType (&)[Count]
  182. {
  183. copy_array_impl<ElementType[Count]>()(in, out);
  184. return out;
  185. }
  186. /////////////////////////////////////////////////////////////////////////////////////////
  187. /////////////////////////////////////////////////////////////////////////////////////////
  188. // make_unqiue implementation for C++11
  189. template<class T> struct _Unique_if
  190. {
  191. using _Single_object = std::unique_ptr<T>;
  192. };
  193. template<class T> struct _Unique_if<T[]>
  194. {
  195. using _Unknown_bound = std::unique_ptr<T[]>;
  196. };
  197. template<class T, size_t N> struct _Unique_if<T[N]>
  198. {
  199. using _Known_bound = void;
  200. };
  201. template<class T, class... Args>
  202. typename _Unique_if<T>::_Single_object
  203. make_unique(Args&&... args)
  204. {
  205. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  206. }
  207. template<class T>
  208. typename _Unique_if<T>::_Unknown_bound
  209. make_unique(size_t n)
  210. {
  211. using U = typename std::remove_extent<T>::type;
  212. return std::unique_ptr<T>(new U[n]());
  213. }
  214. template<class T, class... Args>
  215. typename _Unique_if<T>::_Known_bound
  216. make_unique(Args&&...) = delete;
  217. /////////////////////////////////////////////////////////////////////////////////////////
  218. /////////////////////////////////////////////////////////////////////////////////////////
  219. /////////////////////////////////////////////////////////////////////////////////////////
  220. template <class T>
  221. RTTR_CONSTEXPR RTTR_INLINE add_const_t<T>& as_const(T& value) RTTR_NOEXCEPT
  222. {
  223. return value;
  224. }
  225. /////////////////////////////////////////////////////////////////////////////////////////
  226. /////////////////////////////////////////////////////////////////////////////////////////
  227. /////////////////////////////////////////////////////////////////////////////////////////
  228. template<typename T>
  229. RTTR_FORCE_INLINE typename std::enable_if<std::is_pointer<T>::value, void*>::type as_void_ptr(const T& obj)
  230. {
  231. return const_cast<void*>(reinterpret_cast<const volatile void*>(obj));
  232. }
  233. template<typename T>
  234. RTTR_FORCE_INLINE typename std::enable_if<!std::is_pointer<T>::value, void*>::type as_void_ptr(const T& obj)
  235. {
  236. return const_cast<void*>(reinterpret_cast<const volatile void*>(&obj));
  237. }
  238. /////////////////////////////////////////////////////////////////////////////////////////
  239. /////////////////////////////////////////////////////////////////////////////////////////
  240. /////////////////////////////////////////////////////////////////////////////////////////
  241. /*!
  242. * Helper class to iterate in a ranged-based for loops backwards through a container.
  243. * use it like following:
  244. * \code{.cpp}
  245. * for(const auto& value: reverse(my_vector))
  246. * std::cout << value << std::endl;
  247. * \endcode
  248. */
  249. template<class T>
  250. class reverse_wrapper
  251. {
  252. public:
  253. reverse_wrapper(T& container) : m_container(container) { }
  254. decltype(std::declval<T>().rbegin()) begin() { return m_container.rbegin(); }
  255. decltype(std::declval<T>().rend()) end() { return m_container.rend(); }
  256. decltype(std::declval<T>().crbegin()) begin() const { return m_container.crbegin(); }
  257. decltype(std::declval<T>().crend()) end() const { return m_container.crend(); }
  258. private:
  259. reverse_wrapper<T>& operator=(const reverse_wrapper<T>& other);
  260. T& m_container;
  261. };
  262. template<class T>
  263. class reverse_move_wrapper
  264. {
  265. public:
  266. reverse_move_wrapper(T&& container) : m_container(std::move(container)) { }
  267. decltype(std::declval<T>().rbegin()) begin() { return m_container.rbegin(); }
  268. decltype(std::declval<T>().rend()) end() { return m_container.rend(); }
  269. decltype(std::declval<T>().crbegin()) begin() const { return m_container.crbegin(); }
  270. decltype(std::declval<T>().crend()) end() const { return m_container.crend(); }
  271. private:
  272. T m_container;
  273. };
  274. template<class T>
  275. auto reverse(T&& container) -> typename std::conditional< std::is_lvalue_reference<T>::value, reverse_wrapper<T>, reverse_move_wrapper<T> >::type
  276. {
  277. return { std::forward<T>(container) };
  278. }
  279. /////////////////////////////////////////////////////////////////////////////////////////
  280. /////////////////////////////////////////////////////////////////////////////////////////
  281. /////////////////////////////////////////////////////////////////////////////////////////
  282. template<typename T>
  283. using return_type_normal = add_pointer_t< remove_pointers_t<T> >;
  284. template<typename T, typename Tp = remove_reference_t<T>>
  285. using raw_addressof_return_type = std::conditional< is_function_ptr< remove_pointers_except_one_t<Tp> >::value,
  286. add_pointer_t< remove_pointers_except_one_t<Tp> >,
  287. return_type_normal<Tp> >;
  288. template<typename T>
  289. using raw_addressof_return_type_t = typename raw_addressof_return_type<T>::type;
  290. template<typename T, typename Enable = void>
  291. struct raw_addressof_impl
  292. {
  293. static RTTR_INLINE raw_addressof_return_type_t<T> get(T& data)
  294. {
  295. return std::addressof(data);
  296. }
  297. };
  298. template<typename T>
  299. using is_raw_void_pointer = std::is_same<void*, add_pointer_t< raw_type_t<T> > >;
  300. template<typename T>
  301. using is_void_pointer = std::integral_constant<bool, std::is_pointer<T>::value && is_raw_void_pointer<T>::value && pointer_count<T>::value == 1>;
  302. template<typename T>
  303. struct raw_addressof_impl<T, enable_if_t<(std::is_pointer<T>::value && pointer_count<T>::value >= 1 && !is_void_pointer<T>::value) ||
  304. (pointer_count<T>::value == 1 && std::is_member_pointer<remove_pointer_t<T> >::value)
  305. > >
  306. {
  307. static RTTR_INLINE raw_addressof_return_type_t<T> get(T& data)
  308. {
  309. return raw_addressof_impl< remove_pointer_t<T> >::get(*data);
  310. }
  311. };
  312. template<typename T>
  313. struct raw_addressof_impl<T, enable_if_t<is_void_pointer<T>::value> >
  314. {
  315. static RTTR_INLINE raw_addressof_return_type_t<T> get(T& data)
  316. {
  317. return data; // void pointer cannot be dereferenced to type "void"
  318. }
  319. };
  320. /*!
  321. * \brief This function will return from its raw type \p T
  322. * its address as pointer.
  323. *
  324. * \see detail::raw_type
  325. *
  326. * \return The address of the raw type from the given object \p data as pointer.
  327. */
  328. template<typename T>
  329. static RTTR_INLINE raw_addressof_return_type_t<T> raw_addressof(T& data)
  330. {
  331. return raw_addressof_impl<T>::get(data);
  332. }
  333. /////////////////////////////////////////////////////////////////////////////////////////
  334. /////////////////////////////////////////////////////////////////////////////////////////
  335. /////////////////////////////////////////////////////////////////////////////////////////
  336. /*!
  337. * The \ref move_wrapper class wraps a move-only type in a copyable object.
  338. *
  339. */
  340. template<typename T>
  341. struct move_wrapper
  342. {
  343. move_wrapper(T&& value) : m_value(std::move(value)) { }
  344. move_wrapper(const move_wrapper& other) : m_value(std::move(other.m_value)) { }
  345. move_wrapper(move_wrapper&& other) : m_value(std::move(other.m_value)) { }
  346. move_wrapper& operator=(const move_wrapper& other)
  347. {
  348. m_value = std::move(other.m_value);
  349. return *this;
  350. }
  351. move_wrapper& operator=(move_wrapper&& other)
  352. {
  353. m_value = std::move(other.m_value);
  354. return *this;
  355. }
  356. mutable T m_value;
  357. };
  358. /*!
  359. * \brief This function creates an instance of a move_wrapper class for type \p T.
  360. *
  361. * \return An instance of move_wrapper<T>.
  362. */
  363. template<typename T>
  364. static RTTR_INLINE move_wrapper<T> make_rref(T&& value)
  365. {
  366. return {std::move(value)};
  367. }
  368. /////////////////////////////////////////////////////////////////////////////////////////
  369. /////////////////////////////////////////////////////////////////////////////////////////
  370. /////////////////////////////////////////////////////////////////////////////////////////
  371. /*!
  372. * \brief When the given shared_ptr \p obj is empty, it will create a new default one,
  373. * otherwise returns a copy.
  374. */
  375. template<typename T>
  376. static RTTR_INLINE std::shared_ptr<T> create_if_empty(const std::shared_ptr<T>& obj)
  377. {
  378. return (obj.get() ? obj : std::make_shared<T>());
  379. }
  380. /////////////////////////////////////////////////////////////////////////////////////////
  381. /*!
  382. * \brief Generates a hash value for continuous sequence of char's
  383. */
  384. RTTR_INLINE static std::size_t generate_hash(const char* text, std::size_t length)
  385. {
  386. const std::size_t magic_prime = static_cast<std::size_t>(0x01000193);
  387. std::size_t hash = static_cast<std::size_t>(0xcbf29ce4);
  388. for (std::size_t i = 0; i < length; ++i)
  389. hash = (hash ^ text[i]) * magic_prime;
  390. return hash;
  391. }
  392. /////////////////////////////////////////////////////////////////////////////////////////
  393. // custom has functor, to make sure that "std::string" and "rttr::string_view" uses the same hashing algorithm
  394. template <typename T>
  395. struct hash;
  396. template <>
  397. struct hash<std::string>
  398. {
  399. public:
  400. size_t operator()(const std::string& text) const
  401. {
  402. return generate_hash(text.data(), text.length());
  403. }
  404. };
  405. /////////////////////////////////////////////////////////////////////////////////////////
  406. template<typename T>
  407. inline enable_if_t<std::is_same<T, std::string>::value || std::is_same<T, std::wstring>::value, bool>
  408. starts_with(const T& big_str, const T& small_str)
  409. {
  410. return (big_str.compare(0, small_str.size(), small_str) == 0);
  411. }
  412. template<typename T>
  413. inline enable_if_t<std::is_same<T, std::string>::value || std::is_same<T, std::wstring>::value, bool>
  414. ends_with(const T& big_str, const T& small_str)
  415. {
  416. return (big_str.size() >= small_str.size() &&
  417. big_str.compare(big_str.size() - small_str.size(), small_str.size(), small_str) == 0);
  418. }
  419. /////////////////////////////////////////////////////////////////////////////////////////
  420. /*!
  421. * A simple identity function. Returns the same object, without doing anything.
  422. */
  423. template<typename T>
  424. static RTTR_INLINE T& identity_func(T& func) { return func; }
  425. /////////////////////////////////////////////////////////////////////////////////////////
  426. } // end namespace detail
  427. } // end namespace rttr
  428. #ifdef RTTR_NO_CXX17_NOEXCEPT_FUNC_TYPE
  429. RTTR_END_DISABLE_EXCEPT_TYPE_WARNING
  430. #endif
  431. #endif //RTTR_UTILITY_H_