array.hpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. //
  12. // The implementation of array has been adapted from libc++
  13. // (http://libcxx.llvm.org).
  14. //
  15. //===----------------------------------------------------------------------===//
  16. //
  17. // The LLVM Compiler Infrastructure
  18. //
  19. // This file is dual licensed under the MIT and the University of Illinois Open
  20. // Source Licenses. See LICENSE.TXT for details.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. #ifndef RANGES_V3_TEST_ARRAY_HPP
  24. #define RANGES_V3_TEST_ARRAY_HPP
  25. #include <stdexcept>
  26. #include <range/v3/range_fwd.hpp>
  27. #include <range/v3/iterator/operations.hpp>
  28. #include <range/v3/algorithm/fill_n.hpp>
  29. #include <range/v3/algorithm/swap_ranges.hpp>
  30. #include <range/v3/algorithm/equal.hpp>
  31. #include <range/v3/algorithm/lexicographical_compare.hpp>
  32. #include <range/v3/utility/swap.hpp>
  33. namespace test {
  34. /// \addtogroup group-utility
  35. /// A std::array with constexpr support
  36. template<typename T, std::size_t N>
  37. struct array
  38. {
  39. using self = array;
  40. using value_type = T;
  41. using reference = value_type&;
  42. using const_reference = value_type const&;
  43. using iterator = value_type*;
  44. using const_iterator = value_type const*;
  45. using pointer = value_type*;
  46. using const_pointer = value_type const*;
  47. using size_type = std::size_t;
  48. using difference_type = std::ptrdiff_t;
  49. using reverse_iterator = ranges::reverse_iterator<iterator>;
  50. using const_reverse_iterator = ranges::reverse_iterator<const_iterator>;
  51. value_type elems_[N > 0 ? N : 1];
  52. constexpr /*c++14*/ void fill(const value_type& u)
  53. {
  54. ranges::fill_n(elems_, N, u);
  55. }
  56. constexpr /*c++14*/
  57. void swap(array& a) noexcept(ranges::is_nothrow_swappable<T>::value)
  58. {
  59. ranges::swap_ranges(elems_, elems_ + N, a.elems_);
  60. }
  61. // iterators:
  62. constexpr /*c++14*/
  63. iterator begin() noexcept
  64. {
  65. return iterator(elems_);
  66. }
  67. constexpr /*c++14*/
  68. const_iterator begin() const noexcept
  69. {
  70. return const_iterator(elems_);
  71. }
  72. constexpr /*c++14*/
  73. iterator end() noexcept
  74. {
  75. return iterator(elems_ + N);
  76. }
  77. constexpr /*c++14*/
  78. const_iterator end() const noexcept
  79. {
  80. return const_iterator(elems_ + N);
  81. }
  82. constexpr /*c++14*/
  83. reverse_iterator rbegin() noexcept
  84. {
  85. return reverse_iterator(end());
  86. }
  87. constexpr /*c++14*/
  88. const_reverse_iterator rbegin() const noexcept
  89. {
  90. return const_reverse_iterator(end());
  91. }
  92. constexpr /*c++14*/
  93. reverse_iterator rend() noexcept
  94. {
  95. return reverse_iterator(begin());
  96. }
  97. constexpr /*c++14*/
  98. const_reverse_iterator rend() const noexcept
  99. {
  100. return const_reverse_iterator(begin());
  101. }
  102. constexpr /*c++14*/
  103. const_iterator cbegin() const noexcept
  104. {
  105. return begin();
  106. }
  107. constexpr /*c++14*/
  108. const_iterator cend() const noexcept
  109. {
  110. return end();
  111. }
  112. constexpr /*c++14*/
  113. const_reverse_iterator crbegin() const noexcept
  114. {
  115. return rbegin();
  116. }
  117. constexpr /*c++14*/
  118. const_reverse_iterator crend() const noexcept
  119. {
  120. return rend();
  121. }
  122. // capacity:
  123. constexpr /*c++14*/
  124. size_type size() const noexcept
  125. {
  126. return N;
  127. }
  128. constexpr /*c++14*/
  129. size_type max_size() const noexcept
  130. {
  131. return N;
  132. }
  133. constexpr /*c++14*/
  134. bool empty() const noexcept
  135. {
  136. return N == 0;
  137. }
  138. // element access:
  139. constexpr /*c++14*/ reference operator[](size_type n)
  140. {
  141. return elems_[n];
  142. }
  143. constexpr /*c++14*/ const_reference operator[](size_type n) const
  144. {
  145. return elems_[n];
  146. }
  147. constexpr /*c++14*/ reference at(size_type n)
  148. {
  149. if (n >= N)
  150. throw std::out_of_range("array::at");
  151. return elems_[n];
  152. }
  153. constexpr /*c++14*/ const_reference at(size_type n) const
  154. {
  155. if (n >= N)
  156. throw std::out_of_range("array::at");
  157. return elems_[n];
  158. }
  159. constexpr /*c++14*/ reference front()
  160. {
  161. return elems_[0];
  162. }
  163. constexpr /*c++14*/ const_reference front() const
  164. {
  165. return elems_[0];
  166. }
  167. constexpr /*c++14*/ reference back()
  168. {
  169. return elems_[N > 0 ? N-1 : 0];
  170. }
  171. constexpr /*c++14*/ const_reference back() const
  172. {
  173. return elems_[N > 0 ? N-1 : 0];
  174. }
  175. constexpr /*c++14*/
  176. value_type* data() noexcept
  177. {
  178. return elems_;
  179. }
  180. constexpr /*c++14*/
  181. const value_type* data() const noexcept
  182. {
  183. return elems_;
  184. }
  185. };
  186. template<class T, size_t N>
  187. constexpr /*c++14*/
  188. bool
  189. operator==(const array<T, N>& x, const array<T, N>& y)
  190. {
  191. return ranges::equal(x.elems_, x.elems_ + N, y.elems_);
  192. }
  193. template<class T, size_t N>
  194. constexpr /*c++14*/
  195. bool
  196. operator!=(const array<T, N>& x, const array<T, N>& y)
  197. {
  198. return !(x == y);
  199. }
  200. template<class T, size_t N>
  201. constexpr /*c++14*/
  202. bool
  203. operator<(const array<T, N>& x, const array<T, N>& y)
  204. {
  205. return ranges::lexicographical_compare(x.elems_, x.elems_ + N, y.elems_, y.elems_ + N);
  206. }
  207. template<class T, size_t N>
  208. constexpr /*c++14*/
  209. bool
  210. operator>(const array<T, N>& x, const array<T, N>& y)
  211. {
  212. return y < x;
  213. }
  214. template<class T, size_t N>
  215. constexpr /*c++14*/
  216. bool
  217. operator<=(const array<T, N>& x, const array<T, N>& y)
  218. {
  219. return !(y < x);
  220. }
  221. template<class T, size_t N>
  222. constexpr /*c++14*/
  223. bool
  224. operator>=(const array<T, N>& x, const array<T, N>& y)
  225. {
  226. return !(x < y);
  227. }
  228. template<class T, size_t N>
  229. constexpr /*c++14*/
  230. auto swap(array<T, N>& x, array<T, N>& y)
  231. noexcept(ranges::is_nothrow_swappable<T>::value)
  232. -> typename std::enable_if<ranges::is_swappable<T>::value, void>::type
  233. {
  234. x.swap(y);
  235. }
  236. template<size_t I, class T, size_t N>
  237. constexpr /*c++14*/
  238. T& get(array<T, N>& a) noexcept
  239. {
  240. static_assert(I < N, "Index out of bounds in ranges::get<> (ranges::array)");
  241. return a.elems_[I];
  242. }
  243. template<size_t I, class T, size_t N>
  244. constexpr /*c++14*/
  245. const T& get(const array<T, N>& a) noexcept
  246. {
  247. static_assert(I < N, "Index out of bounds in ranges::get<> (const ranges::array)");
  248. return a.elems_[I];
  249. }
  250. template<size_t I, class T, size_t N>
  251. constexpr /*c++14*/
  252. T && get(array<T, N>&& a) noexcept
  253. {
  254. static_assert(I < N, "Index out of bounds in ranges::get<> (ranges::array &&)");
  255. return std::move(a.elems_[I]);
  256. }
  257. template<class T, std::size_t N>
  258. constexpr /*c++14*/ void swap(array<T, N>& a, array<T, N>& b) {
  259. for(std::size_t i = 0; i != N; ++i) {
  260. auto tmp = std::move(a[i]);
  261. a[i] = std::move(b[i]);
  262. b[i] = std::move(tmp);
  263. }
  264. }
  265. } // namespace test
  266. RANGES_DIAGNOSTIC_PUSH
  267. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  268. namespace std
  269. {
  270. template<class T, size_t N>
  271. class tuple_size<test::array<T, N>>
  272. : public integral_constant<size_t, N> {};
  273. template<size_t I, class T, size_t N>
  274. class tuple_element<I, test::array<T, N> >
  275. {
  276. public:
  277. using type = T;
  278. };
  279. } // namespace std
  280. RANGES_DIAGNOSTIC_POP
  281. #endif // RANGES_V3_TEST_ARRAY_HPP