array.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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 <iterator>
  42. #include <stdexcept>
  43. #include <boost/assert.hpp>
  44. #include <boost/core/invoke_swap.hpp>
  45. #include <boost/static_assert.hpp>
  46. #include <boost/throw_exception.hpp>
  47. #include <algorithm>
  48. // FIXES for broken compilers
  49. #include <boost/config.hpp>
  50. namespace boost {
  51. template<class T, std::size_t N>
  52. class array {
  53. public:
  54. T elems[N]; // fixed-size array of elements of type T
  55. public:
  56. // type definitions
  57. typedef T value_type;
  58. typedef T* iterator;
  59. typedef const T* const_iterator;
  60. typedef T& reference;
  61. typedef const T& const_reference;
  62. typedef std::size_t size_type;
  63. typedef std::ptrdiff_t difference_type;
  64. // iterator support
  65. iterator begin() { return elems; }
  66. const_iterator begin() const { return elems; }
  67. const_iterator cbegin() const { return elems; }
  68. iterator end() { return elems+N; }
  69. const_iterator end() const { return elems+N; }
  70. const_iterator cend() const { return elems+N; }
  71. // reverse iterator support
  72. #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
  73. typedef std::reverse_iterator<iterator> reverse_iterator;
  74. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  75. #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
  76. typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
  77. value_type, reference, iterator, difference_type> reverse_iterator;
  78. typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
  79. value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
  80. #else
  81. // workaround for broken reverse_iterator implementations
  82. typedef std::reverse_iterator<iterator,T> reverse_iterator;
  83. typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
  84. #endif
  85. reverse_iterator rbegin() { return reverse_iterator(end()); }
  86. const_reverse_iterator rbegin() const {
  87. return const_reverse_iterator(end());
  88. }
  89. const_reverse_iterator crbegin() const {
  90. return const_reverse_iterator(end());
  91. }
  92. reverse_iterator rend() { return reverse_iterator(begin()); }
  93. const_reverse_iterator rend() const {
  94. return const_reverse_iterator(begin());
  95. }
  96. const_reverse_iterator crend() const {
  97. return const_reverse_iterator(begin());
  98. }
  99. // operator[]
  100. reference operator[](size_type i)
  101. {
  102. return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
  103. }
  104. /*BOOST_CONSTEXPR*/ const_reference operator[](size_type i) const
  105. {
  106. return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i];
  107. }
  108. // at() with range check
  109. reference at(size_type i) { return rangecheck(i), elems[i]; }
  110. /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; }
  111. // front() and back()
  112. reference front()
  113. {
  114. return elems[0];
  115. }
  116. BOOST_CONSTEXPR const_reference front() const
  117. {
  118. return elems[0];
  119. }
  120. reference back()
  121. {
  122. return elems[N-1];
  123. }
  124. BOOST_CONSTEXPR const_reference back() const
  125. {
  126. return elems[N-1];
  127. }
  128. // size is constant
  129. static BOOST_CONSTEXPR size_type size() { return N; }
  130. static BOOST_CONSTEXPR bool empty() { return false; }
  131. static BOOST_CONSTEXPR size_type max_size() { return N; }
  132. enum { static_size = N };
  133. // swap (note: linear complexity)
  134. void swap (array<T,N>& y) {
  135. for (size_type i = 0; i < N; ++i)
  136. boost::core::invoke_swap(elems[i],y.elems[i]);
  137. }
  138. // direct access to data (read-only)
  139. const T* data() const { return elems; }
  140. T* data() { return elems; }
  141. // use array as C array (direct read/write access to data)
  142. T* c_array() { return elems; }
  143. // assignment with type conversion
  144. template <typename T2>
  145. array<T,N>& operator= (const array<T2,N>& rhs) {
  146. std::copy(rhs.begin(),rhs.end(), begin());
  147. return *this;
  148. }
  149. // assign one value to all elements
  150. void assign (const T& value) { fill ( value ); } // A synonym for fill
  151. void fill (const T& value)
  152. {
  153. std::fill_n(begin(),size(),value);
  154. }
  155. // check range (may be private because it is static)
  156. static BOOST_CONSTEXPR bool rangecheck (size_type i) {
  157. return i >= size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true;
  158. }
  159. };
  160. template< class T >
  161. class array< T, 0 > {
  162. public:
  163. // type definitions
  164. typedef T value_type;
  165. typedef T* iterator;
  166. typedef const T* const_iterator;
  167. typedef T& reference;
  168. typedef const T& const_reference;
  169. typedef std::size_t size_type;
  170. typedef std::ptrdiff_t difference_type;
  171. // iterator support
  172. iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); }
  173. const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
  174. const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); }
  175. iterator end() { return begin(); }
  176. const_iterator end() const { return begin(); }
  177. const_iterator cend() const { return cbegin(); }
  178. // reverse iterator support
  179. #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
  180. typedef std::reverse_iterator<iterator> reverse_iterator;
  181. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  182. #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
  183. typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
  184. value_type, reference, iterator, difference_type> reverse_iterator;
  185. typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
  186. value_type, const_reference, const_iterator, difference_type> const_reverse_iterator;
  187. #else
  188. // workaround for broken reverse_iterator implementations
  189. typedef std::reverse_iterator<iterator,T> reverse_iterator;
  190. typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
  191. #endif
  192. reverse_iterator rbegin() { return reverse_iterator(end()); }
  193. const_reverse_iterator rbegin() const {
  194. return const_reverse_iterator(end());
  195. }
  196. const_reverse_iterator crbegin() const {
  197. return const_reverse_iterator(end());
  198. }
  199. reverse_iterator rend() { return reverse_iterator(begin()); }
  200. const_reverse_iterator rend() const {
  201. return const_reverse_iterator(begin());
  202. }
  203. const_reverse_iterator crend() const {
  204. return const_reverse_iterator(begin());
  205. }
  206. // operator[]
  207. reference operator[](size_type /*i*/)
  208. {
  209. return failed_rangecheck();
  210. }
  211. /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const
  212. {
  213. return failed_rangecheck();
  214. }
  215. // at() with range check
  216. reference at(size_type /*i*/) { return failed_rangecheck(); }
  217. /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const { return failed_rangecheck(); }
  218. // front() and back()
  219. reference front()
  220. {
  221. return failed_rangecheck();
  222. }
  223. BOOST_CONSTEXPR const_reference front() const
  224. {
  225. return failed_rangecheck();
  226. }
  227. reference back()
  228. {
  229. return failed_rangecheck();
  230. }
  231. BOOST_CONSTEXPR const_reference back() const
  232. {
  233. return failed_rangecheck();
  234. }
  235. // size is constant
  236. static BOOST_CONSTEXPR size_type size() { return 0; }
  237. static BOOST_CONSTEXPR bool empty() { return true; }
  238. static BOOST_CONSTEXPR size_type max_size() { return 0; }
  239. enum { static_size = 0 };
  240. void swap (array<T,0>& /*y*/) {
  241. }
  242. // direct access to data (read-only)
  243. const T* data() const { return 0; }
  244. T* data() { return 0; }
  245. // use array as C array (direct read/write access to data)
  246. T* c_array() { return 0; }
  247. // assignment with type conversion
  248. template <typename T2>
  249. array<T,0>& operator= (const array<T2,0>& ) {
  250. return *this;
  251. }
  252. // assign one value to all elements
  253. void assign (const T& value) { fill ( value ); }
  254. void fill (const T& ) {}
  255. // check range (may be private because it is static)
  256. static reference failed_rangecheck () {
  257. std::out_of_range e("attempt to access element of an empty array");
  258. boost::throw_exception(e);
  259. #if defined(BOOST_NO_EXCEPTIONS) || (!defined(BOOST_MSVC) && !defined(__PATHSCALE__))
  260. //
  261. // We need to return something here to keep
  262. // some compilers happy: however we will never
  263. // actually get here....
  264. //
  265. static T placeholder;
  266. return placeholder;
  267. #endif
  268. }
  269. };
  270. // comparisons
  271. template<class T, std::size_t N>
  272. bool operator== (const array<T,N>& x, const array<T,N>& y) {
  273. return std::equal(x.begin(), x.end(), y.begin());
  274. }
  275. template<class T, std::size_t N>
  276. bool operator< (const array<T,N>& x, const array<T,N>& y) {
  277. return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
  278. }
  279. template<class T, std::size_t N>
  280. bool operator!= (const array<T,N>& x, const array<T,N>& y) {
  281. return !(x==y);
  282. }
  283. template<class T, std::size_t N>
  284. bool operator> (const array<T,N>& x, const array<T,N>& y) {
  285. return y<x;
  286. }
  287. template<class T, std::size_t N>
  288. bool operator<= (const array<T,N>& x, const array<T,N>& y) {
  289. return !(y<x);
  290. }
  291. template<class T, std::size_t N>
  292. bool operator>= (const array<T,N>& x, const array<T,N>& y) {
  293. return !(x<y);
  294. }
  295. // global swap()
  296. template<class T, std::size_t N>
  297. inline void swap (array<T,N>& x, array<T,N>& y) {
  298. x.swap(y);
  299. }
  300. #if defined(__SUNPRO_CC)
  301. // Trac ticket #4757; the Sun Solaris compiler can't handle
  302. // syntax like 'T(&get_c_array(boost::array<T,N>& arg))[N]'
  303. //
  304. // We can't just use this for all compilers, because the
  305. // borland compilers can't handle this form.
  306. namespace detail {
  307. template <typename T, std::size_t N> struct c_array
  308. {
  309. typedef T type[N];
  310. };
  311. }
  312. // Specific for boost::array: simply returns its elems data member.
  313. template <typename T, std::size_t N>
  314. typename detail::c_array<T,N>::type& get_c_array(boost::array<T,N>& arg)
  315. {
  316. return arg.elems;
  317. }
  318. // Specific for boost::array: simply returns its elems data member.
  319. template <typename T, std::size_t N>
  320. typename detail::c_array<T,N>::type const& get_c_array(const boost::array<T,N>& arg)
  321. {
  322. return arg.elems;
  323. }
  324. #else
  325. // Specific for boost::array: simply returns its elems data member.
  326. template <typename T, std::size_t N>
  327. T(&get_c_array(boost::array<T,N>& arg))[N]
  328. {
  329. return arg.elems;
  330. }
  331. // Const version.
  332. template <typename T, std::size_t N>
  333. const T(&get_c_array(const boost::array<T,N>& arg))[N]
  334. {
  335. return arg.elems;
  336. }
  337. #endif
  338. #if 0
  339. // Overload for std::array, assuming that std::array will have
  340. // explicit conversion functions as discussed at the WG21 meeting
  341. // in Summit, March 2009.
  342. template <typename T, std::size_t N>
  343. T(&get_c_array(std::array<T,N>& arg))[N]
  344. {
  345. return static_cast<T(&)[N]>(arg);
  346. }
  347. // Const version.
  348. template <typename T, std::size_t N>
  349. const T(&get_c_array(const std::array<T,N>& arg))[N]
  350. {
  351. return static_cast<T(&)[N]>(arg);
  352. }
  353. #endif
  354. template <class It> std::size_t hash_range(It, It);
  355. template<class T, std::size_t N>
  356. std::size_t hash_value(const array<T,N>& arr)
  357. {
  358. return boost::hash_range(arr.begin(), arr.end());
  359. }
  360. template <size_t Idx, typename T, size_t N>
  361. T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
  362. BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" );
  363. return arr[Idx];
  364. }
  365. template <size_t Idx, typename T, size_t N>
  366. const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
  367. BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" );
  368. return arr[Idx];
  369. }
  370. } /* namespace boost */
  371. #ifndef BOOST_NO_CXX11_HDR_ARRAY
  372. // If we don't have std::array, I'm assuming that we don't have std::get
  373. namespace std {
  374. template <size_t Idx, typename T, size_t N>
  375. T &get(boost::array<T,N> &arr) BOOST_NOEXCEPT {
  376. BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" );
  377. return arr[Idx];
  378. }
  379. template <size_t Idx, typename T, size_t N>
  380. const T &get(const boost::array<T,N> &arr) BOOST_NOEXCEPT {
  381. BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" );
  382. return arr[Idx];
  383. }
  384. }
  385. #endif
  386. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  387. # pragma warning(pop)
  388. #endif
  389. #endif /*BOOST_ARRAY_HPP*/