You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/collections/array_proxy.hpp
  3. *
  4. * Purpose: Definition of the array_proxy template, which provides managed
  5. * access to arrays, and can be used to avoid polymorphic array
  6. * problems.
  7. *
  8. * Created: 11th November 2002
  9. * Updated: 10th August 2009
  10. *
  11. * Home: http://stlsoft.org/
  12. *
  13. * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
  14. * All rights reserved.
  15. *
  16. * Redistribution and use in source and binary forms, with or without
  17. * modification, are permitted provided that the following conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright notice, this
  20. * list of conditions and the following disclaimer.
  21. * - Redistributions in binary form must reproduce the above copyright notice,
  22. * this list of conditions and the following disclaimer in the documentation
  23. * and/or other materials provided with the distribution.
  24. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  25. * any contributors may be used to endorse or promote products derived from
  26. * this software without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  29. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  34. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  35. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  37. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * ////////////////////////////////////////////////////////////////////// */
  41. /** \file stlsoft/collections/array_proxy.hpp
  42. *
  43. * \brief [C++ only] Definition of the stlsoft::array_proxy
  44. * class template
  45. * (\ref group__library__collections "Collections" Library).
  46. */
  47. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY
  48. #define STLSOFT_INCL_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY
  49. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  50. # define STLSOFT_VER_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY_MAJOR 4
  51. # define STLSOFT_VER_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY_MINOR 0
  52. # define STLSOFT_VER_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY_REVISION 4
  53. # define STLSOFT_VER_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY_EDIT 57
  54. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  55. /* /////////////////////////////////////////////////////////////////////////
  56. * Includes
  57. */
  58. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  59. # include <stlsoft/stlsoft.h>
  60. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  61. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
  62. # include <stlsoft/util/constraints.hpp>
  63. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS */
  64. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  65. # include <stlsoft/collections/util/collections.hpp>
  66. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  67. /* /////////////////////////////////////////////////////////////////////////
  68. * Namespace
  69. */
  70. #ifndef _STLSOFT_NO_NAMESPACE
  71. namespace stlsoft
  72. {
  73. #endif /* _STLSOFT_NO_NAMESPACE */
  74. /* /////////////////////////////////////////////////////////////////////////
  75. * Classes
  76. */
  77. /** \brief Acts as a proxy for built-in arrays, ensuring functions passed array proxies
  78. * have safe access to both array pointer and length
  79. *
  80. * \ingroup group__library__collections
  81. *
  82. * \note This is described in detail in section 14.4 of
  83. * <a href = "http://www.imperfectcplusplus.com/">Imperfect C++</a>.
  84. */
  85. template <ss_typename_param_k T>
  86. class array_proxy
  87. : public stl_collection_tag
  88. {
  89. public:
  90. typedef T value_type;
  91. typedef array_proxy<T> class_type;
  92. typedef value_type* pointer;
  93. typedef value_type* const_pointer; // This is deliberately non-const
  94. typedef value_type* iterator;
  95. typedef value_type* const_iterator; // This is deliberately non-const
  96. typedef value_type& reference;
  97. typedef value_type& const_reference; // This is deliberately non-const
  98. typedef ss_size_t size_type;
  99. /// \name Construction
  100. /// @{
  101. public:
  102. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
  103. /// Conversion constructor, facilitating conversion between polymorphic
  104. /// types of the same size
  105. ///
  106. /// \param d The array proxy of a derived type
  107. template <ss_typename_param_k D>
  108. array_proxy(array_proxy<D> &d)
  109. : m_begin(d.begin())
  110. , m_end(d.end())
  111. {
  112. // Ensures that D is a derived type of T. (Actually that is
  113. // handled in the initialiser list, but putting it here
  114. // makes the intent quite explicit.)
  115. stlsoft_constraint_must_have_base(D, T);
  116. // Ensures that D and T are the same size.
  117. stlsoft_constraint_must_be_same_size(D, T);
  118. }
  119. # ifdef STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
  120. /// Constructs an instance of the array proxy from the given array
  121. ///
  122. /// \param d The array
  123. template <ss_typename_param_k D, ss_size_t N>
  124. ss_explicit_k array_proxy(D (&d)[N])
  125. : m_begin(&d[0])
  126. , m_end(&d[N])
  127. {
  128. // Ensures that D is a derived type of T. (Actually that is
  129. // handled in the initialiser list, but putting it here
  130. // makes the intent quite explicit.)
  131. stlsoft_constraint_must_have_base(D, T);
  132. // Ensures that D and T are the same size.
  133. stlsoft_constraint_must_be_same_size(D, T);
  134. }
  135. /// Constructs an instance of the array proxy from the given array
  136. ///
  137. /// \param t The array
  138. # if defined(STLSOFT_CF_NON_TEMPLATE_CTOR_REQUIRED_WITH_TEMPLATE_CTOR)
  139. template <ss_size_t N>
  140. ss_explicit_k array_proxy(T (&t)[N])
  141. : m_begin(&t[0])
  142. , m_end(&t[N])
  143. {}
  144. # endif /* STLSOFT_CF_NON_TEMPLATE_CTOR_REQUIRED_WITH_TEMPLATE_CTOR */
  145. # endif /* STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
  146. #endif // STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
  147. /// Constructs an instance of the array proxy from the given range
  148. ///
  149. /// \param begin The start point of the range [begin, end)
  150. /// \param end The end point of the range [begin, end)
  151. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
  152. defined(STLSOFT_CF_NON_TEMPLATE_CTOR_REQUIRED_WITH_TEMPLATE_CTOR)
  153. array_proxy(pointer begin, pointer end)
  154. : m_begin(begin)
  155. , m_end(end)
  156. {}
  157. #endif /* !STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT || STLSOFT_CF_NON_TEMPLATE_CTOR_REQUIRED_WITH_TEMPLATE_CTOR */
  158. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
  159. /// Constructs an instance of the array proxy from the given range
  160. ///
  161. /// \param b The start point of the range [begin, end)
  162. /// \param e The end point of the range [begin, end)
  163. template <ss_typename_param_k D>
  164. array_proxy(D *b, D *e)
  165. : m_begin(b)
  166. , m_end(e)
  167. {
  168. // Ensures that D is a derived type of T. (Actually that is
  169. // handled in the initialiser list, but putting it here
  170. // makes the intent quite explicit.)
  171. stlsoft_constraint_must_have_base(D, T);
  172. // Ensures that D and T are the same size.
  173. stlsoft_constraint_must_be_same_size(D, T);
  174. }
  175. #endif // STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
  176. #if !defined(STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT) || \
  177. defined(STLSOFT_CF_NON_TEMPLATE_CTOR_REQUIRED_WITH_TEMPLATE_CTOR)
  178. /// Constructs an instance of the array proxy from the given pointer
  179. ///
  180. /// \param p Pointer to the first element in the range
  181. /// \param n The number of elements in the range
  182. array_proxy(pointer p, ss_size_t n)
  183. : m_begin(p)
  184. , m_end(p + n)
  185. {}
  186. #endif /* !STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT || STLSOFT_CF_NON_TEMPLATE_CTOR_REQUIRED_WITH_TEMPLATE_CTOR */
  187. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
  188. /// Constructs an instance of the array proxy from the given range
  189. ///
  190. /// \param p The start of the range
  191. /// \param n The number of elements in the range
  192. template <ss_typename_param_k D>
  193. array_proxy(D *p, ss_size_t n)
  194. : m_begin(p)
  195. , m_end(p + n)
  196. {
  197. // Ensures that D is a derived type of T. (Actually that is
  198. // handled in the initialiser list, but putting it here
  199. // makes the intent quite explicit.)
  200. stlsoft_constraint_must_have_base(D, T);
  201. // Ensures that D and T are the same size.
  202. stlsoft_constraint_must_be_same_size(D, T);
  203. }
  204. #endif // STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
  205. /// @}
  206. /// \name Attributes
  207. /// @{
  208. public:
  209. /// Returns the base of the array
  210. ///
  211. pointer base()
  212. {
  213. return m_begin;
  214. }
  215. /// Returns the base of the array
  216. ///
  217. pointer base() const
  218. {
  219. return m_begin;
  220. }
  221. /// Returns the number of elements in the sequence
  222. size_type size() const
  223. {
  224. return m_end - m_begin;
  225. }
  226. /// Indicates whether the search sequence is empty
  227. ss_bool_t empty() const
  228. {
  229. return m_begin == m_end;
  230. }
  231. /// Returns the maximum number of elements in the sequence
  232. static size_type max_size()
  233. {
  234. return static_cast<size_type>(-1) / sizeof(value_type);
  235. }
  236. /// @}
  237. /// \name Subscripting
  238. /// @{
  239. public:
  240. /// Returns the element at the given index
  241. ///
  242. /// \param index The offset of the requested element
  243. /// \note No runtime checking of the validity of the index is provided in release builds, only a debug-time assert
  244. reference operator [](ss_size_t index)
  245. {
  246. STLSOFT_MESSAGE_ASSERT("index out of bounds, in array_proxy", !(size() < index));
  247. return m_begin[index];
  248. }
  249. /// Returns the element at the given index
  250. ///
  251. /// \param index The offset of the requested element
  252. /// \note No runtime checking of the validity of the index is provided in release builds, only a debug-time assert
  253. const_reference operator [](ss_size_t index) const
  254. {
  255. STLSOFT_MESSAGE_ASSERT("index out of bounds, in array_proxy", !(size() < index));
  256. return const_cast<pointer>(m_begin)[index];
  257. }
  258. /// @}
  259. /// \name Iteration
  260. /// @{
  261. public:
  262. /// Begins the iteration
  263. ///
  264. /// \return An iterator representing the start of the sequence
  265. iterator begin()
  266. {
  267. return m_begin;
  268. }
  269. /// Ends the iteration
  270. ///
  271. /// \return An iterator representing the end of the sequence
  272. iterator end()
  273. {
  274. return m_end;
  275. }
  276. /// Begins the iteration
  277. ///
  278. /// \return An iterator representing the start of the sequence
  279. const_iterator begin() const
  280. {
  281. return m_begin;
  282. }
  283. /// Ends the iteration
  284. ///
  285. /// \return An iterator representing the end of the sequence
  286. const_iterator end() const
  287. {
  288. return m_end;
  289. }
  290. /// @}
  291. // Members
  292. private:
  293. pointer const m_begin;
  294. pointer const m_end;
  295. // Not to be implemented
  296. private:
  297. array_proxy& operator =(array_proxy const&);
  298. };
  299. /* /////////////////////////////////////////////////////////////////////////
  300. * Creator functions
  301. */
  302. #ifdef STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
  303. template <ss_typename_param_k T, ss_size_t N>
  304. inline array_proxy<T> make_array_proxy(T (&t)[N])
  305. {
  306. return array_proxy<T>(&t[0], &t[N]);
  307. // return array_proxy<T>(t); // This one not used, because CodeWarrior gets confused
  308. }
  309. #endif /* STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
  310. template <ss_typename_param_k T>
  311. inline array_proxy<T> make_array_proxy(T *begin, T *end)
  312. {
  313. return array_proxy<T>(begin, end);
  314. }
  315. template <ss_typename_param_k T>
  316. inline array_proxy<const T> make_array_proxy(T const* begin, T const* end)
  317. {
  318. return array_proxy<const T>(begin, end);
  319. }
  320. template <ss_typename_param_k T>
  321. inline array_proxy<T> make_array_proxy(T *p, ss_size_t n)
  322. {
  323. return array_proxy<T>(p, n);
  324. }
  325. #if 0
  326. template <ss_typename_param_k T>
  327. inline array_proxy<const T> make_array_proxy(T const* p, ss_size_t n)
  328. {
  329. return array_proxy<const T>(p, n);
  330. }
  331. #endif /* 0 */
  332. ////////////////////////////////////////////////////////////////////////////
  333. // Unit-testing
  334. #ifdef STLSOFT_UNITTEST
  335. # include "./unittest/array_proxy_unittest_.h"
  336. #endif /* STLSOFT_UNITTEST */
  337. /* ////////////////////////////////////////////////////////////////////// */
  338. #ifndef _STLSOFT_NO_NAMESPACE
  339. } // namespace stlsoft
  340. #endif /* _STLSOFT_NO_NAMESPACE */
  341. /* ////////////////////////////////////////////////////////////////////// */
  342. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_HPP_ARRAY_PROXY */
  343. /* ///////////////////////////// end of file //////////////////////////// */