array.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. #ifndef BOOST_ARRAY_HPP_INCLUDED
  2. #define BOOST_ARRAY_HPP_INCLUDED
  3. /* The following code declares class array,
  4. * an STL container (as wrapper) for arrays of constant size.
  5. *
  6. * See
  7. * http://www.boost.org/libs/array/
  8. * for documentation.
  9. *
  10. * The original author site is at: http://www.josuttis.com/
  11. *
  12. * (C) Copyright Nicolai M. Josuttis 2001.
  13. *
  14. * Distributed under the Boost Software License, Version 1.0. (See
  15. * accompanying file LICENSE_1_0.txt or copy at
  16. * http://www.boost.org/LICENSE_1_0.txt)
  17. *
  18. * 9 Jan 2013 - (mtc) Added constexpr
  19. * 14 Apr 2012 - (mtc) Added support for boost::hash
  20. * 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility.
  21. * 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group.
  22. * See <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776> or Trac issue #3168
  23. * Eventually, we should remove "assign" which is now a synonym for "fill" (Marshall Clow)
  24. * 10 Mar 2010 - added workaround for SUNCC and !STLPort [trac #3893] (Marshall Clow)
  25. * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis)
  26. * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
  27. * 05 Aug 2001 - minor update (Nico Josuttis)
  28. * 20 Jan 2001 - STLport fix (Beman Dawes)
  29. * 29 Sep 2000 - Initial Revision (Nico Josuttis)
  30. *
  31. * Jan 29, 2004
  32. */
  33. #include <boost/config.hpp>
  34. #include <boost/config/workaround.hpp>
  35. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  36. # pragma warning(push)
  37. # pragma warning(disable: 4510) // boost::array<T,N>' : default constructor could not be generated
  38. # pragma warning(disable: 4512) // boost::array<T,N>' : assignment operator could not be generated
  39. # pragma warning(disable: 4610) // class 'boost::array<T,N>' can never be instantiated - user defined constructor required
  40. # pragma warning(disable: 4702) // unreachable code
  41. #endif
  42. #include <boost/assert.hpp>
  43. #include <boost/static_assert.hpp>
  44. #include <boost/throw_exception.hpp>
  45. #include <iterator>
  46. #include <stdexcept>
  47. #include <utility>
  48. #include <cstddef>
  49. #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L
  50. # if __has_include(<compare>)
  51. # include <compare>
  52. # endif
  53. #endif
  54. namespace boost {
  55. template<class T, std::size_t N>
  56. class array {
  57. public:
  58. T elems[N]; // fixed-size array of elements of type T
  59. public:
  60. // type definitions
  61. typedef T value_type;
  62. typedef T* iterator;
  63. typedef const T* const_iterator;
  64. typedef T& reference;
  65. typedef const T& const_reference;
  66. typedef std::size_t size_type;
  67. typedef std::ptrdiff_t difference_type;
  68. // iterator support
  69. BOOST_CXX14_CONSTEXPR iterator begin() BOOST_NOEXCEPT { return elems; }
  70. BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return elems; }
  71. BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return elems; }
  72. BOOST_CXX14_CONSTEXPR iterator end() BOOST_NOEXCEPT { return elems+N; }
  73. BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return elems+N; }
  74. BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return elems+N; }
  75. // reverse iterator support
  76. typedef std::reverse_iterator<iterator> reverse_iterator;
  77. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  78. reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); }
  79. const_reverse_iterator rbegin() const BOOST_NOEXCEPT {
  80. return const_reverse_iterator(end());
  81. }
  82. const_reverse_iterator crbegin() const BOOST_NOEXCEPT {
  83. return const_reverse_iterator(end());
  84. }
  85. reverse_iterator rend() BOOST_NOEXCEPT { return reverse_iterator(begin()); }
  86. const_reverse_iterator rend() const BOOST_NOEXCEPT {
  87. return const_reverse_iterator(begin());
  88. }
  89. const_reverse_iterator crend() const BOOST_NOEXCEPT {
  90. return const_reverse_iterator(begin());
  91. }
  92. // operator[]
  93. BOOST_CXX14_CONSTEXPR reference operator[](size_type i)
  94. {
  95. return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
  96. }
  97. #if !BOOST_WORKAROUND(BOOST_GCC, < 50000)
  98. BOOST_CONSTEXPR
  99. #endif
  100. const_reference operator[](size_type i) const
  101. {
  102. return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
  103. }
  104. // at() with range check
  105. BOOST_CXX14_CONSTEXPR reference at(size_type i) { return rangecheck(i), elems[i]; }
  106. BOOST_CONSTEXPR const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
  107. // front() and back()
  108. BOOST_CXX14_CONSTEXPR reference front()
  109. {
  110. return elems[0];
  111. }
  112. BOOST_CONSTEXPR const_reference front() const
  113. {
  114. return elems[0];
  115. }
  116. BOOST_CXX14_CONSTEXPR reference back()
  117. {
  118. return elems[N-1];
  119. }
  120. BOOST_CONSTEXPR const_reference back() const
  121. {
  122. return elems[N-1];
  123. }
  124. // size is constant
  125. static BOOST_CONSTEXPR size_type size() BOOST_NOEXCEPT { return N; }
  126. static BOOST_CONSTEXPR bool empty() BOOST_NOEXCEPT { return false; }
  127. static BOOST_CONSTEXPR size_type max_size() BOOST_NOEXCEPT { return N; }
  128. enum { static_size = N };
  129. // swap (note: linear complexity)
  130. BOOST_CXX14_CONSTEXPR void swap (array<T,N>& y)
  131. {
  132. std::swap( elems, y.elems );
  133. }
  134. // direct access to data
  135. BOOST_CONSTEXPR const T* data() const BOOST_NOEXCEPT { return elems; }
  136. BOOST_CXX14_CONSTEXPR T* data() BOOST_NOEXCEPT { return elems; }
  137. // obsolete
  138. BOOST_DEPRECATED( "please use `data()` instead" )
  139. T* c_array() BOOST_NOEXCEPT { return elems; }
  140. // assignment with type conversion
  141. template <typename T2>
  142. array<T,N>& operator= (const array<T2,N>& rhs)
  143. {
  144. for( std::size_t i = 0; i < N; ++i )
  145. {
  146. elems[ i ] = rhs.elems[ i ];
  147. }
  148. return *this;
  149. }
  150. // fill with one value
  151. BOOST_CXX14_CONSTEXPR void fill (const T& value)
  152. {
  153. // using elems[ 0 ] as a temporary copy
  154. // avoids the aliasing opportunity betw.
  155. // `value` and `elems`
  156. elems[ 0 ] = value;
  157. for( std::size_t i = 1; i < N; ++i )
  158. {
  159. elems[ i ] = elems[ 0 ];
  160. }
  161. }
  162. // an obsolete synonym for fill
  163. BOOST_DEPRECATED( "please use `fill` instead" )
  164. void assign (const T& value) { fill ( value ); }
  165. // check range (may be private because it is static)
  166. static BOOST_CONSTEXPR bool rangecheck (size_type i) {
  167. return i >= size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true;
  168. }
  169. };
  170. template< class T >
  171. class array< T, 0 > {
  172. public:
  173. struct {} elems; // enables initialization with = {{}}
  174. public:
  175. // type definitions
  176. typedef T value_type;
  177. typedef T* iterator;
  178. typedef const T* const_iterator;
  179. typedef T& reference;
  180. typedef const T& const_reference;
  181. typedef std::size_t size_type;
  182. typedef std::ptrdiff_t difference_type;
  183. // iterator support
  184. BOOST_CXX14_CONSTEXPR iterator begin() BOOST_NOEXCEPT { return data(); }
  185. BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return data(); }
  186. BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return data(); }
  187. BOOST_CXX14_CONSTEXPR iterator end() BOOST_NOEXCEPT { return begin(); }
  188. BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return begin(); }
  189. BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return cbegin(); }
  190. // reverse iterator support
  191. typedef std::reverse_iterator<iterator> reverse_iterator;
  192. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  193. reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); }
  194. const_reverse_iterator rbegin() const BOOST_NOEXCEPT {
  195. return const_reverse_iterator(end());
  196. }
  197. const_reverse_iterator crbegin() const BOOST_NOEXCEPT {
  198. return const_reverse_iterator(end());
  199. }
  200. reverse_iterator rend() BOOST_NOEXCEPT { return reverse_iterator(begin()); }
  201. const_reverse_iterator rend() const BOOST_NOEXCEPT {
  202. return const_reverse_iterator(begin());
  203. }
  204. const_reverse_iterator crend() const BOOST_NOEXCEPT {
  205. return const_reverse_iterator(begin());
  206. }
  207. // operator[]
  208. reference operator[](size_type /*i*/)
  209. {
  210. return failed_rangecheck();
  211. }
  212. const_reference operator[](size_type /*i*/) const
  213. {
  214. return failed_rangecheck();
  215. }
  216. // at() with range check
  217. reference at(size_type /*i*/) { return failed_rangecheck(); }
  218. const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
  219. // front() and back()
  220. reference front()
  221. {
  222. return failed_rangecheck();
  223. }
  224. const_reference front() const
  225. {
  226. return failed_rangecheck();
  227. }
  228. reference back()
  229. {
  230. return failed_rangecheck();
  231. }
  232. const_reference back() const
  233. {
  234. return failed_rangecheck();
  235. }
  236. // size is constant
  237. static BOOST_CONSTEXPR size_type size() BOOST_NOEXCEPT { return 0; }
  238. static BOOST_CONSTEXPR bool empty() BOOST_NOEXCEPT { return true; }
  239. static BOOST_CONSTEXPR size_type max_size() BOOST_NOEXCEPT { return 0; }
  240. enum { static_size = 0 };
  241. BOOST_CXX14_CONSTEXPR void swap (array<T,0>& /*y*/)
  242. {
  243. }
  244. // direct access to data
  245. BOOST_CONSTEXPR const T* data() const BOOST_NOEXCEPT { return 0; }
  246. BOOST_CXX14_CONSTEXPR T* data() BOOST_NOEXCEPT { return 0; }
  247. // obsolete
  248. BOOST_DEPRECATED( "please use `data()` instead" )
  249. T* c_array() BOOST_NOEXCEPT { return 0; }
  250. // assignment with type conversion
  251. template <typename T2>
  252. array<T,0>& operator= (const array<T2,0>& ) {
  253. return *this;
  254. }
  255. // an obsolete synonym for fill
  256. BOOST_DEPRECATED( "please use `fill` instead" )
  257. void assign (const T& value) { fill ( value ); }
  258. // fill with one value
  259. BOOST_CXX14_CONSTEXPR void fill (const T& ) {}
  260. // check range (may be private because it is static)
  261. static reference failed_rangecheck ()
  262. {
  263. boost::throw_exception( std::out_of_range( "attempt to access element of an empty array" ) );
  264. }
  265. };
  266. // comparisons
  267. template<class T, std::size_t N>
  268. BOOST_CXX14_CONSTEXPR bool operator== (const array<T,N>& x, const array<T,N>& y)
  269. {
  270. for( std::size_t i = 0; i < N; ++i )
  271. {
  272. if( !( x[ i ] == y[ i ] ) ) return false;
  273. }
  274. return true;
  275. }
  276. #if BOOST_WORKAROUND(BOOST_GCC, < 90000)
  277. template<class T>
  278. BOOST_CXX14_CONSTEXPR bool operator== (const array<T, 0>& /*x*/, const array<T, 0>& /*y*/)
  279. {
  280. return true;
  281. }
  282. #endif
  283. template<class T, std::size_t N>
  284. BOOST_CXX14_CONSTEXPR bool operator!= (const array<T,N>& x, const array<T,N>& y) {
  285. return !(x==y);
  286. }
  287. template<class T, std::size_t N>
  288. BOOST_CXX14_CONSTEXPR bool operator< (const array<T,N>& x, const array<T,N>& y)
  289. {
  290. for( std::size_t i = 0; i < N; ++i )
  291. {
  292. if( x[ i ] < y[ i ] ) return true;
  293. if( y[ i ] < x[ i ] ) return false;
  294. }
  295. return false;
  296. }
  297. #if BOOST_WORKAROUND(BOOST_GCC, < 90000)
  298. template<class T>
  299. BOOST_CXX14_CONSTEXPR bool operator< (const array<T, 0>& /*x*/, const array<T, 0>& /*y*/)
  300. {
  301. return false;
  302. }
  303. #endif
  304. template<class T, std::size_t N>
  305. BOOST_CXX14_CONSTEXPR bool operator> (const array<T,N>& x, const array<T,N>& y) {
  306. return y<x;
  307. }
  308. template<class T, std::size_t N>
  309. BOOST_CXX14_CONSTEXPR bool operator<= (const array<T,N>& x, const array<T,N>& y) {
  310. return !(y<x);
  311. }
  312. template<class T, std::size_t N>
  313. BOOST_CXX14_CONSTEXPR bool operator>= (const array<T,N>& x, const array<T,N>& y) {
  314. return !(x<y);
  315. }
  316. // global swap()
  317. template<class T, std::size_t N>
  318. BOOST_CXX14_CONSTEXPR inline void swap (array<T,N>& x, array<T,N>& y) {
  319. x.swap(y);
  320. }
  321. #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L
  322. # if __has_include(<compare>)
  323. template<class T, std::size_t N>
  324. constexpr auto operator<=> (const array<T,N>& x, const array<T,N>& y)
  325. -> decltype( x.elems[ 0 ] <=> y.elems[ 0 ] )
  326. {
  327. for( std::size_t i = 0; i < N; ++i )
  328. {
  329. auto r = x.elems[ i ] <=> y.elems[ i ];
  330. if( r != 0 ) return r;
  331. }
  332. return std::strong_ordering::equal;
  333. }
  334. template<class T>
  335. constexpr auto operator<=> (const array<T,0>& /*x*/, const array<T,0>& /*y*/)
  336. -> std::strong_ordering
  337. {
  338. return std::strong_ordering::equal;
  339. }
  340. # endif
  341. #endif
  342. // undocumented and obsolete
  343. template <typename T, std::size_t N>
  344. BOOST_DEPRECATED( "please use `elems` instead" )
  345. T(&get_c_array(boost::array<T,N>& arg))[N]
  346. {
  347. return arg.elems;
  348. }
  349. // Const version.
  350. template <typename T, std::size_t N>
  351. BOOST_DEPRECATED( "please use `elems` instead" )
  352. const T(&get_c_array(const boost::array<T,N>& arg))[N]
  353. {
  354. return arg.elems;
  355. }
  356. template <size_t Idx, typename T, size_t N>
  357. BOOST_CXX14_CONSTEXPR T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT
  358. {
  359. BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" );
  360. return arr[Idx];
  361. }
  362. template <size_t Idx, typename T, size_t N>
  363. BOOST_CONSTEXPR const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT
  364. {
  365. BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" );
  366. return arr[Idx];
  367. }
  368. template<class T, std::size_t N>
  369. BOOST_CXX14_CONSTEXPR array<T, N> to_array( T const (&a)[ N ] )
  370. {
  371. array<T, N> r = {};
  372. for( std::size_t i = 0; i < N; ++i )
  373. {
  374. r[ i ] = a[ i ];
  375. }
  376. return r;
  377. }
  378. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  379. template<class T, std::size_t N>
  380. BOOST_CXX14_CONSTEXPR array<T, N> to_array( T (&&a)[ N ] )
  381. {
  382. array<T, N> r = {};
  383. for( std::size_t i = 0; i < N; ++i )
  384. {
  385. r[ i ] = std::move( a[ i ] );
  386. }
  387. return r;
  388. }
  389. template<class T, std::size_t N>
  390. BOOST_CXX14_CONSTEXPR array<T, N> to_array( T const (&&a)[ N ] )
  391. {
  392. array<T, N> r = {};
  393. for( std::size_t i = 0; i < N; ++i )
  394. {
  395. r[ i ] = a[ i ];
  396. }
  397. return r;
  398. }
  399. #endif
  400. } /* namespace boost */
  401. #ifndef BOOST_NO_CXX11_HDR_ARRAY
  402. // If we don't have std::array, I'm assuming that we don't have std::get
  403. namespace std {
  404. template <size_t Idx, typename T, size_t N>
  405. BOOST_DEPRECATED( "please use `boost::get` instead" )
  406. T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
  407. BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" );
  408. return arr[Idx];
  409. }
  410. template <size_t Idx, typename T, size_t N>
  411. BOOST_DEPRECATED( "please use `boost::get` instead" )
  412. const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
  413. BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" );
  414. return arr[Idx];
  415. }
  416. }
  417. #endif
  418. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  419. # pragma warning(pop)
  420. #endif
  421. #endif // #ifndef BOOST_ARRAY_HPP_INCLUDED