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.

300 lines
10 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: rangelib/indexed_range.hpp
  3. *
  4. * Purpose: Indexed range adaptor class.
  5. *
  6. * Created: 11th October 2004
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2004-2009, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file rangelib/indexed_range.hpp Integral range class */
  40. #ifndef RANGELIB_INCL_RANGELIB_HPP_INDEXED_RANGE
  41. #define RANGELIB_INCL_RANGELIB_HPP_INDEXED_RANGE
  42. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  43. # define RANGELIB_VER_RANGELIB_HPP_INDEXED_RANGE_MAJOR 2
  44. # define RANGELIB_VER_RANGELIB_HPP_INDEXED_RANGE_MINOR 4
  45. # define RANGELIB_VER_RANGELIB_HPP_INDEXED_RANGE_REVISION 2
  46. # define RANGELIB_VER_RANGELIB_HPP_INDEXED_RANGE_EDIT 33
  47. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  48. /* /////////////////////////////////////////////////////////////////////////
  49. * Auto-generation and compatibility
  50. */
  51. /*
  52. [Incompatibilies-start]
  53. STLSOFT_COMPILER_IS_BORLAND:
  54. STLSOFT_COMPILER_IS_MSVC: _MSC_VER < 1200
  55. STLSOFT_COMPILER_IS_MWERKS: (__MWERKS__ & 0xFF00) < 0x3000
  56. [Incompatibilies-end]
  57. */
  58. /* /////////////////////////////////////////////////////////////////////////
  59. * Includes
  60. */
  61. #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGELIB
  62. # include <rangelib/rangelib.hpp>
  63. #endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGELIB */
  64. #if defined(STLSOFT_COMPILER_IS_BORLAND) || \
  65. ( defined(STLSOFT_COMPILER_IS_MWERKS) && \
  66. ((__MWERKS__ & 0xFF00) < 0x3000))
  67. # error This file is not compatible with the current compiler
  68. #endif /* compiler */
  69. #ifndef STLSOFT_INCL_STLSOFT_META_HPP_CAPABILITIES
  70. # include <stlsoft/meta/capabilities.hpp>
  71. #endif /* !STLSOFT_INCL_STLSOFT_META_HPP_CAPABILITIES */
  72. #if defined(STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED)
  73. # ifndef STLSOFT_INCL_STLSOFT_META_HPP_MEMBER_TRAITS
  74. # include <stlsoft/meta/member_traits.hpp>
  75. # endif /* !STLSOFT_INCL_STLSOFT_META_HPP_MEMBER_TRAITS */
  76. # ifndef STLSOFT_INCL_STLSOFT_META_TYPEFIXER_HPP_REFERENCE
  77. # include <stlsoft/meta/typefixer/reference.hpp>
  78. # endif /* !STLSOFT_INCL_STLSOFT_META_TYPEFIXER_HPP_REFERENCE */
  79. #endif /* STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED */
  80. #ifndef RANGELIB_INCL_RANGELIB_HPP_OPERATOR_ADAPTORS
  81. # include <rangelib/operator_adaptors.hpp>
  82. #endif /* !RANGELIB_INCL_RANGELIB_HPP_OPERATOR_ADAPTORS */
  83. #ifdef STLSOFT_UNITTEST
  84. # ifndef RANGELIB_INCL_RANGELIB_HPP_INTEGRAL_RANGE
  85. # include <rangelib/integral_range.hpp>
  86. # endif /* !RANGELIB_INCL_RANGELIB_HPP_INTEGRAL_RANGE */
  87. #endif /* STLSOFT_UNITTEST */
  88. /* /////////////////////////////////////////////////////////////////////////
  89. * Namespace
  90. */
  91. #ifndef RANGELIB_NO_NAMESPACE
  92. # if defined(_STLSOFT_NO_NAMESPACE) || \
  93. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  94. /* There is no stlsoft namespace, so must define ::rangelib */
  95. namespace rangelib
  96. {
  97. # else
  98. /* Define stlsoft::rangelib_project */
  99. namespace stlsoft
  100. {
  101. namespace rangelib_project
  102. {
  103. # endif /* _STLSOFT_NO_NAMESPACE */
  104. #endif /* !RANGELIB_NO_NAMESPACE */
  105. /* /////////////////////////////////////////////////////////////////////////
  106. * Classes
  107. */
  108. /** \brief Adapts a range and provides an integral count alongside the range
  109. *
  110. * \ingroup group__library__rangelib
  111. *
  112. * \param R The adapted range type
  113. * \param I The integer type
  114. */
  115. template< class R
  116. , ss_typename_param_k I = int
  117. >
  118. class indexed_range
  119. #if defined(STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED)
  120. : public /* ss_typename_type_k */ operator_adaptor_selector<indexed_range<R, I>, R>::type // This provides the operator forms of the methods. R can serve as its own traits here
  121. #else /* STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED */
  122. : public non_mutating_operator_adaptor< indexed_range<R, I>, R>
  123. #endif /* STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED */
  124. , public R::range_tag_type
  125. {
  126. /// \name Member Types
  127. /// @{
  128. private:
  129. #ifdef STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED
  130. /// Indicates whether the parameterising sequence type has a \c reference member
  131. ///
  132. /// \note We can't use the type fixer in a fully correct way here, because
  133. /// most compilers do not detect reference / const_reference members, so we
  134. /// take a guess and use the presence/absence of the iterator membertype as
  135. /// the sign of the presence of the reference member type.
  136. # if defined(STLSOFT_COMPILER_IS_MWERKS)
  137. enum { HAS_MEMBER_REFERENCE = 0 != member_traits<R>::has_member_reference };
  138. # else /* ? compiler */
  139. enum { HAS_MEMBER_REFERENCE = 0 != member_traits<R>::has_member_iterator };
  140. # endif /* compiler */
  141. #endif /* STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED */
  142. public:
  143. /// The of the adapted range
  144. typedef R adapted_range_type;
  145. /// The index type
  146. typedef I index_type;
  147. /// The range tag type
  148. #if !defined(STLSOFT_COMPILER_IS_MSVC) || \
  149. _MSC_VER > 1200
  150. typedef ss_typename_type_k R::range_tag_type range_tag_type;
  151. #endif /* compiler */
  152. /// The value type
  153. typedef ss_typename_type_k R::value_type value_type;
  154. /// The non-mutating (const) type
  155. typedef ss_typename_type_k R::const_reference const_reference;
  156. #ifdef STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED
  157. /// The mutating (non-const) type
  158. typedef ss_typename_type_k select_first_type_if< ss_typename_type_k ::stlsoft::typefixer::fixer_reference<R, HAS_MEMBER_REFERENCE>::reference
  159. , const_reference
  160. , HAS_MEMBER_REFERENCE
  161. >::type reference;
  162. #endif /* STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED */
  163. /// The current instantiation of the type
  164. typedef indexed_range<R, I> class_type;
  165. /// @}
  166. /// \name Construction
  167. /// @{
  168. public:
  169. /// Constructor
  170. ///
  171. /// \param r The range
  172. /// \param index The initial index of the range
  173. ss_explicit_k indexed_range(R r, index_type index = 0)
  174. : m_range(r)
  175. , m_index(index)
  176. {}
  177. /// @}
  178. /// \name Notional Range methods
  179. /// @{
  180. public:
  181. /// Indicates whether the range is open
  182. ss_bool_t is_open() const
  183. {
  184. return m_range.is_open();
  185. }
  186. #ifdef STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED
  187. /// Returns the current value in the range
  188. reference current()
  189. {
  190. STLSOFT_ASSERT(is_open());
  191. return m_range.current();
  192. }
  193. #endif /* STLSOFT_CF_HAS_MEMBER_TYPE_SUPPORTED */
  194. /// Returns the current value in the range
  195. const_reference current() const
  196. {
  197. STLSOFT_ASSERT(is_open());
  198. return m_range.current();
  199. }
  200. /// Advances the current position in the range
  201. class_type& advance()
  202. {
  203. STLSOFT_MESSAGE_ASSERT("Attempting to increment the range past its end point", is_open());
  204. ++m_range;
  205. ++m_index;
  206. return *this;
  207. }
  208. /// @}
  209. #if 0
  210. /// \name Iterable Range methods
  211. /// @{
  212. public:
  213. /// Returns an iterator to the current position of the range
  214. iterator begin()
  215. {
  216. return m_range.begin();
  217. }
  218. /// Returns an iterator to the end of the range
  219. iterator end()
  220. {
  221. return m_range.end();
  222. }
  223. /// Returns an iterator to the current position of the range
  224. const_iterator begin() const
  225. {
  226. return m_range.begin();
  227. }
  228. /// Returns an iterator to the end of the range
  229. const_iterator end() const
  230. {
  231. return m_range.end();
  232. }
  233. /// @}
  234. #endif /* 0 */
  235. /// \name Iterable Range methods
  236. /// @{
  237. public:
  238. index_type index() const
  239. {
  240. return m_index;
  241. }
  242. /// @}
  243. // Members
  244. private:
  245. adapted_range_type m_range;
  246. index_type m_index;
  247. };
  248. ////////////////////////////////////////////////////////////////////////////
  249. // Unit-testing
  250. #ifdef STLSOFT_UNITTEST
  251. # include "./unittest/indexed_range_unittest_.h"
  252. #endif /* STLSOFT_UNITTEST */
  253. /* ////////////////////////////////////////////////////////////////////// */
  254. #ifndef RANGELIB_NO_NAMESPACE
  255. # if defined(_STLSOFT_NO_NAMESPACE) || \
  256. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  257. } // namespace rangelib
  258. # else
  259. } // namespace rangelib_project
  260. } // namespace stlsoft
  261. # endif /* _STLSOFT_NO_NAMESPACE */
  262. #endif /* !RANGELIB_NO_NAMESPACE */
  263. /* ////////////////////////////////////////////////////////////////////// */
  264. #endif /* !RANGELIB_INCL_RANGELIB_HPP_INDEXED_RANGE */
  265. /* ///////////////////////////// end of file //////////////////////////// */