container_helpers.hxx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. // -*-c++-*-
  2. // vim: set ft=cpp:
  3. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  4. file LICENSE.rst or https://cmake.org/licensing for details. */
  5. #pragma once
  6. #include <iterator> // IWYU pragma: keep
  7. #if __cplusplus < 201402L || defined(_MSVC_LANG) && _MSVC_LANG < 201402L
  8. # include <initializer_list>
  9. #endif
  10. #if __cplusplus < 202002L || defined(_MSVC_LANG) && _MSVC_LANG < 202002L
  11. # include <cstddef>
  12. # include <type_traits>
  13. #endif
  14. namespace cm {
  15. using std::begin;
  16. using std::end;
  17. #if __cplusplus < 201402L || defined(_MSVC_LANG) && _MSVC_LANG < 201402L
  18. template <typename C>
  19. # if defined(_MSC_VER) && _MSC_VER < 1900
  20. inline auto cbegin(C const& c)
  21. # else
  22. inline constexpr auto cbegin(C const& c) noexcept(noexcept(std::begin(c)))
  23. # endif
  24. -> decltype(std::begin(c))
  25. {
  26. return std::begin(c);
  27. }
  28. template <typename C>
  29. # if defined(_MSC_VER) && _MSC_VER < 1900
  30. inline auto cend(C const& c)
  31. # else
  32. inline constexpr auto cend(C const& c) noexcept(noexcept(std::end(c)))
  33. # endif
  34. -> decltype(std::end(c))
  35. {
  36. return std::end(c);
  37. }
  38. template <typename C>
  39. # if defined(_MSC_VER) && _MSC_VER < 1900
  40. inline auto rbegin(C& c)
  41. # else
  42. inline constexpr auto rbegin(C& c)
  43. # endif
  44. -> decltype(c.rbegin())
  45. {
  46. return c.rbegin();
  47. }
  48. template <typename C>
  49. # if defined(_MSC_VER) && _MSC_VER < 1900
  50. inline auto rbegin(C const& c)
  51. # else
  52. inline constexpr auto rbegin(C const& c)
  53. # endif
  54. -> decltype(c.rbegin())
  55. {
  56. return c.rbegin();
  57. }
  58. template <typename T, std::size_t N>
  59. # if defined(_MSC_VER) && _MSC_VER < 1900
  60. inline std::reverse_iterator<T*> rbegin(T (&array)[N])
  61. # else
  62. inline constexpr std::reverse_iterator<T*> rbegin(T (&array)[N]) noexcept
  63. # endif
  64. {
  65. return std::reverse_iterator<T*>(array + N);
  66. }
  67. template <typename T>
  68. # if defined(_MSC_VER) && _MSC_VER < 1900
  69. inline std::reverse_iterator<T const*> rbegin(std::initializer_list<T> il)
  70. # else
  71. inline constexpr std::reverse_iterator<T const*> rbegin(
  72. std::initializer_list<T> il) noexcept
  73. # endif
  74. {
  75. return std::reverse_iterator<T const*>(il.end());
  76. }
  77. template <typename C>
  78. # if defined(_MSC_VER) && _MSC_VER < 1900
  79. inline auto rend(C& c)
  80. # else
  81. inline constexpr auto rend(C& c)
  82. # endif
  83. -> decltype(c.rend())
  84. {
  85. return c.rend();
  86. }
  87. template <typename C>
  88. # if defined(_MSC_VER) && _MSC_VER < 1900
  89. inline auto rend(C const& c)
  90. # else
  91. inline constexpr auto rend(C const& c)
  92. # endif
  93. -> decltype(c.rend())
  94. {
  95. return c.rend();
  96. }
  97. template <typename T, std::size_t N>
  98. # if defined(_MSC_VER) && _MSC_VER < 1900
  99. inline std::reverse_iterator<T*> rend(T (&array)[N])
  100. # else
  101. inline constexpr std::reverse_iterator<T*> rend(T (&array)[N]) noexcept
  102. # endif
  103. {
  104. return std::reverse_iterator<T*>(array);
  105. }
  106. template <typename T>
  107. # if defined(_MSC_VER) && _MSC_VER < 1900
  108. inline std::reverse_iterator<T const*> rend(std::initializer_list<T> il)
  109. # else
  110. inline constexpr std::reverse_iterator<T const*> rend(
  111. std::initializer_list<T> il) noexcept
  112. # endif
  113. {
  114. return std::reverse_iterator<T const*>(il.begin());
  115. }
  116. template <typename C>
  117. # if defined(_MSC_VER) && _MSC_VER < 1900
  118. inline auto crbegin(C const& c)
  119. # else
  120. inline constexpr auto crbegin(C const& c)
  121. # endif
  122. -> decltype(cm::rbegin(c))
  123. {
  124. return cm::rbegin(c);
  125. }
  126. template <typename C>
  127. # if defined(_MSC_VER) && _MSC_VER < 1900
  128. inline auto crend(C const& c)
  129. # else
  130. inline constexpr auto crend(C const& c)
  131. # endif
  132. -> decltype(cm::rend(c))
  133. {
  134. return cm::rend(c);
  135. }
  136. #else
  137. using std::cbegin;
  138. using std::cend;
  139. using std::rbegin;
  140. using std::rend;
  141. using std::crbegin;
  142. using std::crend;
  143. #endif
  144. #if __cplusplus < 201703L || defined(_MSVC_LANG) && _MSVC_LANG < 201703L
  145. template <typename C>
  146. # if defined(_MSC_VER) && _MSC_VER < 1900
  147. inline auto size(C const& c)
  148. # else
  149. inline constexpr auto size(C const& c) noexcept(noexcept(c.size()))
  150. # endif
  151. -> decltype(c.size())
  152. {
  153. return c.size();
  154. }
  155. template <typename T, std::size_t N>
  156. # if defined(_MSC_VER) && _MSC_VER < 1900
  157. inline std::size_t size(T const (&)[N])
  158. # else
  159. inline constexpr std::size_t size(T const (&)[N]) noexcept
  160. # endif
  161. {
  162. return N;
  163. }
  164. template <typename C>
  165. # if defined(_MSC_VER) && _MSC_VER < 1900
  166. inline auto empty(C const& c)
  167. # else
  168. inline constexpr auto empty(C const& c) noexcept(noexcept(c.empty()))
  169. # endif
  170. -> decltype(c.empty())
  171. {
  172. return c.empty();
  173. }
  174. template <typename T, std::size_t N>
  175. # if defined(_MSC_VER) && _MSC_VER < 1900
  176. inline bool empty(T const (&)[N])
  177. # else
  178. inline constexpr bool empty(T const (&)[N]) noexcept
  179. # endif
  180. {
  181. return false;
  182. }
  183. template <typename E>
  184. # if defined(_MSC_VER) && _MSC_VER < 1900
  185. inline bool empty(std::initializer_list<E> il)
  186. # else
  187. inline constexpr bool empty(std::initializer_list<E> il) noexcept
  188. # endif
  189. {
  190. return il.size() == 0;
  191. }
  192. template <typename C>
  193. # if defined(_MSC_VER) && _MSC_VER < 1900
  194. inline auto data(C& c) -> decltype(c.data())
  195. # else
  196. inline constexpr auto data(C& c) noexcept(noexcept(c.data()))
  197. # endif
  198. -> decltype(c.data())
  199. {
  200. return c.data();
  201. }
  202. template <typename C>
  203. # if defined(_MSC_VER) && _MSC_VER < 1900
  204. inline auto data(C const& c)
  205. # else
  206. inline constexpr auto data(C const& c) noexcept(noexcept(c.data()))
  207. # endif
  208. -> decltype(c.data())
  209. {
  210. return c.data();
  211. }
  212. template <typename T, std::size_t N>
  213. # if defined(_MSC_VER) && _MSC_VER < 1900
  214. inline T* data(T (&array)[N])
  215. # else
  216. inline constexpr T* data(T (&array)[N]) noexcept
  217. # endif
  218. {
  219. return array;
  220. }
  221. template <typename E>
  222. # if defined(_MSC_VER) && _MSC_VER < 1900
  223. inline E const* data(std::initializer_list<E> il)
  224. # else
  225. inline constexpr E const* data(std::initializer_list<E> il) noexcept
  226. # endif
  227. {
  228. return il.begin();
  229. }
  230. #else
  231. using std::size;
  232. using std::empty;
  233. using std::data;
  234. #endif
  235. #if __cplusplus < 202002L || defined(_MSVC_LANG) && _MSVC_LANG < 202002L
  236. template <typename C>
  237. # if defined(_MSC_VER) && _MSC_VER < 1900
  238. inline auto ssize(C const& c)
  239. # else
  240. inline constexpr auto ssize(C const& c)
  241. # endif
  242. -> typename std::common_type<
  243. std::ptrdiff_t, typename std::make_signed<decltype(c.size())>::type>::type
  244. {
  245. using signed_type = typename std::make_signed<decltype(c.size())>::type;
  246. using result_type =
  247. typename std::common_type<std::ptrdiff_t, signed_type>::type;
  248. return static_cast<result_type>(c.size());
  249. }
  250. template <typename T, std::ptrdiff_t N>
  251. # if defined(_MSC_VER) && _MSC_VER < 1900
  252. inline std::ptrdiff_t ssize(T const (&)[N])
  253. # else
  254. inline constexpr std::ptrdiff_t ssize(T const (&)[N]) noexcept
  255. # endif
  256. {
  257. return N;
  258. }
  259. #else
  260. using std::ssize;
  261. #endif
  262. } // namespace cm