array.hpp 16 KB

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