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 24 #ifndef RANGES_V3_TEST_ARRAY_HPP 25 #define RANGES_V3_TEST_ARRAY_HPP 26 27 #include <stdexcept> 28 #include <range/v3/range_fwd.hpp> 29 #include <range/v3/iterator/operations.hpp> 30 #include <range/v3/algorithm/fill_n.hpp> 31 #include <range/v3/algorithm/swap_ranges.hpp> 32 #include <range/v3/algorithm/equal.hpp> 33 #include <range/v3/algorithm/lexicographical_compare.hpp> 34 #include <range/v3/utility/swap.hpp> 35 36 namespace test { 37 38 /// \addtogroup group-utility 39 /// A std::array with constexpr support 40 template<typename T, std::size_t N> 41 struct array 42 { 43 using self = array; 44 using value_type = T; 45 using reference = value_type&; 46 using const_reference = value_type const&; 47 using iterator = value_type*; 48 using const_iterator = value_type const*; 49 using pointer = value_type*; 50 using const_pointer = value_type const*; 51 using size_type = std::size_t; 52 using difference_type = std::ptrdiff_t; 53 using reverse_iterator = ranges::reverse_iterator<iterator>; 54 using const_reverse_iterator = ranges::reverse_iterator<const_iterator>; 55 56 value_type elems_[N > 0 ? N : 1]; 57 filltest::array58 constexpr /*c++14*/ void fill(const value_type& u) 59 { 60 ranges::fill_n(elems_, N, u); 61 } 62 constexpr /*c++14*/ swaptest::array63 void swap(array& a) noexcept(ranges::is_nothrow_swappable<T>::value) 64 { 65 ranges::swap_ranges(elems_, elems_ + N, a.elems_); 66 } 67 // iterators: 68 constexpr /*c++14*/ begintest::array69 iterator begin() noexcept 70 { 71 return iterator(elems_); 72 } 73 constexpr /*c++14*/ begintest::array74 const_iterator begin() const noexcept 75 { 76 return const_iterator(elems_); 77 } 78 constexpr /*c++14*/ endtest::array79 iterator end() noexcept 80 { 81 return iterator(elems_ + N); 82 } 83 constexpr /*c++14*/ endtest::array84 const_iterator end() const noexcept 85 { 86 return const_iterator(elems_ + N); 87 } 88 constexpr /*c++14*/ rbegintest::array89 reverse_iterator rbegin() noexcept 90 { 91 return reverse_iterator(end()); 92 } 93 constexpr /*c++14*/ rbegintest::array94 const_reverse_iterator rbegin() const noexcept 95 { 96 return const_reverse_iterator(end()); 97 } 98 constexpr /*c++14*/ rendtest::array99 reverse_iterator rend() noexcept 100 { 101 return reverse_iterator(begin()); 102 } 103 constexpr /*c++14*/ rendtest::array104 const_reverse_iterator rend() const noexcept 105 { 106 return const_reverse_iterator(begin()); 107 } 108 constexpr /*c++14*/ cbegintest::array109 const_iterator cbegin() const noexcept 110 { 111 return begin(); 112 } 113 constexpr /*c++14*/ cendtest::array114 const_iterator cend() const noexcept 115 { 116 return end(); 117 } 118 constexpr /*c++14*/ crbegintest::array119 const_reverse_iterator crbegin() const noexcept 120 { 121 return rbegin(); 122 } 123 constexpr /*c++14*/ crendtest::array124 const_reverse_iterator crend() const noexcept 125 { 126 return rend(); 127 } 128 // capacity: 129 constexpr /*c++14*/ sizetest::array130 size_type size() const noexcept 131 { 132 return N; 133 } 134 constexpr /*c++14*/ max_sizetest::array135 size_type max_size() const noexcept 136 { 137 return N; 138 } 139 constexpr /*c++14*/ emptytest::array140 bool empty() const noexcept 141 { 142 return N == 0; 143 } 144 // element access: operator []test::array145 constexpr /*c++14*/ reference operator[](size_type n) 146 { 147 return elems_[n]; 148 } operator []test::array149 constexpr /*c++14*/ const_reference operator[](size_type n) const 150 { 151 return elems_[n]; 152 } attest::array153 constexpr /*c++14*/ reference at(size_type n) 154 { 155 if (n >= N) 156 throw std::out_of_range("array::at"); 157 return elems_[n]; 158 } attest::array159 constexpr /*c++14*/ const_reference at(size_type n) const 160 { 161 if (n >= N) 162 throw std::out_of_range("array::at"); 163 return elems_[n]; 164 } fronttest::array165 constexpr /*c++14*/ reference front() 166 { 167 return elems_[0]; 168 } fronttest::array169 constexpr /*c++14*/ const_reference front() const 170 { 171 return elems_[0]; 172 } backtest::array173 constexpr /*c++14*/ reference back() 174 { 175 return elems_[N > 0 ? N-1 : 0]; 176 } backtest::array177 constexpr /*c++14*/ const_reference back() const 178 { 179 return elems_[N > 0 ? N-1 : 0]; 180 } 181 constexpr /*c++14*/ datatest::array182 value_type* data() noexcept 183 { 184 return elems_; 185 } 186 constexpr /*c++14*/ datatest::array187 const value_type* data() const noexcept 188 { 189 return elems_; 190 } 191 }; 192 193 template<class T, size_t N> 194 constexpr /*c++14*/ 195 bool operator ==(const array<T,N> & x,const array<T,N> & y)196 operator==(const array<T, N>& x, const array<T, N>& y) 197 { 198 return ranges::equal(x.elems_, x.elems_ + N, y.elems_); 199 } 200 template<class T, size_t N> 201 constexpr /*c++14*/ 202 bool operator !=(const array<T,N> & x,const array<T,N> & y)203 operator!=(const array<T, N>& x, const array<T, N>& y) 204 { 205 return !(x == y); 206 } 207 template<class T, size_t N> 208 constexpr /*c++14*/ 209 bool operator <(const array<T,N> & x,const array<T,N> & y)210 operator<(const array<T, N>& x, const array<T, N>& y) 211 { 212 return ranges::lexicographical_compare(x.elems_, x.elems_ + N, y.elems_, y.elems_ + N); 213 } 214 template<class T, size_t N> 215 constexpr /*c++14*/ 216 bool operator >(const array<T,N> & x,const array<T,N> & y)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 operator <=(const array<T,N> & x,const array<T,N> & y)224 operator<=(const array<T, N>& x, const array<T, N>& y) 225 { 226 return !(y < x); 227 } 228 229 template<class T, size_t N> 230 constexpr /*c++14*/ 231 bool operator >=(const array<T,N> & x,const array<T,N> & y)232 operator>=(const array<T, N>& x, const array<T, N>& y) 233 { 234 return !(x < y); 235 } 236 237 template<class T, size_t N> 238 constexpr /*c++14*/ swap(array<T,N> & x,array<T,N> & y)239 auto swap(array<T, N>& x, array<T, N>& y) 240 noexcept(ranges::is_nothrow_swappable<T>::value) 241 -> typename std::enable_if<ranges::is_swappable<T>::value, void>::type 242 { 243 x.swap(y); 244 } 245 246 template<size_t I, class T, size_t N> 247 constexpr /*c++14*/ get(array<T,N> & a)248 T& get(array<T, N>& a) noexcept 249 { 250 static_assert(I < N, "Index out of bounds in ranges::get<> (ranges::array)"); 251 return a.elems_[I]; 252 } 253 254 template<size_t I, class T, size_t N> 255 constexpr /*c++14*/ get(const array<T,N> & a)256 const T& get(const array<T, N>& a) noexcept 257 { 258 static_assert(I < N, "Index out of bounds in ranges::get<> (const ranges::array)"); 259 return a.elems_[I]; 260 } 261 262 template<size_t I, class T, size_t N> 263 constexpr /*c++14*/ get(array<T,N> && a)264 T && get(array<T, N>&& a) noexcept 265 { 266 static_assert(I < N, "Index out of bounds in ranges::get<> (ranges::array &&)"); 267 return std::move(a.elems_[I]); 268 } 269 270 template<class T, std::size_t N> swap(array<T,N> & a,array<T,N> & b)271 constexpr /*c++14*/ void swap(array<T, N>& a, array<T, N>& b) { 272 for(std::size_t i = 0; i != N; ++i) { 273 auto tmp = std::move(a[i]); 274 a[i] = std::move(b[i]); 275 b[i] = std::move(tmp); 276 } 277 } 278 } // namespace test 279 280 RANGES_DIAGNOSTIC_PUSH 281 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS 282 283 namespace std 284 { 285 286 template<class T, size_t N> 287 class tuple_size<test::array<T, N>> 288 : public integral_constant<size_t, N> {}; 289 290 template<size_t I, class T, size_t N> 291 class tuple_element<I, test::array<T, N> > 292 { 293 public: 294 using type = T; 295 }; 296 297 } // namespace std 298 299 RANGES_DIAGNOSTIC_POP 300 301 #endif // RANGES_V3_TEST_ARRAY_HPP 302