iterator.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. // (C) Copyright David Abrahams 2002.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Boost versions of
  6. //
  7. // std::iterator_traits<>::iterator_category
  8. // std::iterator_traits<>::difference_type
  9. // std::distance()
  10. //
  11. // ...for all compilers and iterators
  12. //
  13. // Additionally, if X is a pointer
  14. // std::iterator_traits<X>::pointer
  15. // Otherwise, if partial specialization is supported or X is not a pointer
  16. // std::iterator_traits<X>::value_type
  17. // std::iterator_traits<X>::pointer
  18. // std::iterator_traits<X>::reference
  19. //
  20. // See http://www.boost.org for most recent version including documentation.
  21. // Revision History
  22. // 04 Mar 2001 - More attempted fixes for Intel C++ (David Abrahams)
  23. // 03 Mar 2001 - Put all implementation into namespace
  24. // boost::detail::iterator_traits_. Some progress made on fixes
  25. // for Intel compiler. (David Abrahams)
  26. // 02 Mar 2001 - Changed BOOST_MSVC to BOOST_MSVC_STD_ITERATOR in a few
  27. // places. (Jeremy Siek)
  28. // 19 Feb 2001 - Improved workarounds for stock MSVC6; use yes_type and
  29. // no_type from type_traits.hpp; stopped trying to remove_cv
  30. // before detecting is_pointer, in honor of the new type_traits
  31. // semantics. (David Abrahams)
  32. // 13 Feb 2001 - Make it work with nearly all standard-conforming iterators
  33. // under raw VC6. The one category remaining which will fail is
  34. // that of iterators derived from std::iterator but not
  35. // boost::iterator and which redefine difference_type.
  36. // 11 Feb 2001 - Clean away code which can never be used (David Abrahams)
  37. // 09 Feb 2001 - Always have a definition for each traits member, even if it
  38. // can't be properly deduced. These will be incomplete types in
  39. // some cases (undefined<void>), but it helps suppress MSVC errors
  40. // elsewhere (David Abrahams)
  41. // 07 Feb 2001 - Support for more of the traits members where possible, making
  42. // this useful as a replacement for std::iterator_traits<T> when
  43. // used as a default template parameter.
  44. // 06 Feb 2001 - Removed useless #includes of standard library headers
  45. // (David Abrahams)
  46. #ifndef ITERATOR_DWA122600_HPP_
  47. # define ITERATOR_DWA122600_HPP_
  48. # include <boost/config.hpp>
  49. # include <iterator>
  50. // STLPort 4.0 and betas have a bug when debugging is enabled and there is no
  51. // partial specialization: instead of an iterator_category typedef, the standard
  52. // container iterators have _Iterator_category.
  53. //
  54. // Also, whether debugging is enabled or not, there is a broken specialization
  55. // of std::iterator<output_iterator_tag,void,void,void,void> which has no
  56. // typedefs but iterator_category.
  57. # if defined(__SGI_STL_PORT)
  58. # if (__SGI_STL_PORT <= 0x410) && !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) && defined(__STL_DEBUG)
  59. # define BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
  60. # endif
  61. # define BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
  62. # endif // STLPort <= 4.1b4 && no partial specialization
  63. # if !defined(BOOST_NO_STD_ITERATOR_TRAITS) \
  64. && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
  65. && !defined(BOOST_MSVC_STD_ITERATOR)
  66. namespace boost { namespace detail {
  67. // Define a new template so it can be specialized
  68. template <class Iterator>
  69. struct iterator_traits
  70. : std::iterator_traits<Iterator>
  71. {};
  72. using std::distance;
  73. }} // namespace boost::detail
  74. # else
  75. # if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
  76. && !defined(BOOST_MSVC_STD_ITERATOR)
  77. // This is the case where everything conforms except BOOST_NO_STD_ITERATOR_TRAITS
  78. namespace boost { namespace detail {
  79. // Rogue Wave Standard Library fools itself into thinking partial
  80. // specialization is missing on some platforms (e.g. Sun), so fails to
  81. // supply iterator_traits!
  82. template <class Iterator>
  83. struct iterator_traits
  84. {
  85. typedef typename Iterator::value_type value_type;
  86. typedef typename Iterator::reference reference;
  87. typedef typename Iterator::pointer pointer;
  88. typedef typename Iterator::difference_type difference_type;
  89. typedef typename Iterator::iterator_category iterator_category;
  90. };
  91. template <class T>
  92. struct iterator_traits<T*>
  93. {
  94. typedef T value_type;
  95. typedef T& reference;
  96. typedef T* pointer;
  97. typedef std::ptrdiff_t difference_type;
  98. typedef std::random_access_iterator_tag iterator_category;
  99. };
  100. template <class T>
  101. struct iterator_traits<T const*>
  102. {
  103. typedef T value_type;
  104. typedef T const& reference;
  105. typedef T const* pointer;
  106. typedef std::ptrdiff_t difference_type;
  107. typedef std::random_access_iterator_tag iterator_category;
  108. };
  109. }} // namespace boost::detail
  110. # else
  111. # include <boost/type_traits/remove_const.hpp>
  112. # include <boost/type_traits/detail/yes_no_type.hpp>
  113. # include <boost/type_traits/is_pointer.hpp>
  114. # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  115. # include <boost/type_traits/is_same.hpp>
  116. # include <boost/type_traits/remove_pointer.hpp>
  117. # endif
  118. # ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
  119. # include <boost/type_traits/is_base_and_derived.hpp>
  120. # endif
  121. # include <boost/mpl/if.hpp>
  122. # include <boost/mpl/has_xxx.hpp>
  123. # include <cstddef>
  124. // should be the last #include
  125. # include "boost/type_traits/detail/bool_trait_def.hpp"
  126. namespace boost { namespace detail {
  127. BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
  128. BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
  129. BOOST_MPL_HAS_XXX_TRAIT_DEF(pointer)
  130. BOOST_MPL_HAS_XXX_TRAIT_DEF(difference_type)
  131. BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
  132. // is_mutable_iterator --
  133. //
  134. // A metafunction returning true iff T is a mutable iterator type
  135. // with a nested value_type. Will only work portably with iterators
  136. // whose operator* returns a reference, but that seems to be OK for
  137. // the iterators supplied by Dinkumware. Some input iterators may
  138. // compile-time if they arrive here, and if the compiler is strict
  139. // about not taking the address of an rvalue.
  140. // This one detects ordinary mutable iterators - the result of
  141. // operator* is convertible to the value_type.
  142. template <class T>
  143. type_traits::yes_type is_mutable_iterator_helper(T const*, BOOST_DEDUCED_TYPENAME T::value_type*);
  144. // Since you can't take the address of an rvalue, the guts of
  145. // is_mutable_iterator_impl will fail if we use &*t directly. This
  146. // makes sure we can still work with non-lvalue iterators.
  147. template <class T> T* mutable_iterator_lvalue_helper(T& x);
  148. int mutable_iterator_lvalue_helper(...);
  149. // This one detects output iterators such as ostream_iterator which
  150. // return references to themselves.
  151. template <class T>
  152. type_traits::yes_type is_mutable_iterator_helper(T const*, T const*);
  153. type_traits::no_type is_mutable_iterator_helper(...);
  154. template <class T>
  155. struct is_mutable_iterator_impl
  156. {
  157. static T t;
  158. BOOST_STATIC_CONSTANT(
  159. bool, value = sizeof(
  160. detail::is_mutable_iterator_helper(
  161. (T*)0
  162. , mutable_iterator_lvalue_helper(*t) // like &*t
  163. ))
  164. == sizeof(type_traits::yes_type)
  165. );
  166. };
  167. BOOST_TT_AUX_BOOL_TRAIT_DEF1(
  168. is_mutable_iterator,T,::boost::detail::is_mutable_iterator_impl<T>::value)
  169. // is_full_iterator_traits --
  170. //
  171. // A metafunction returning true iff T has all the requisite nested
  172. // types to satisfy the requirements for a fully-conforming
  173. // iterator_traits implementation.
  174. template <class T>
  175. struct is_full_iterator_traits_impl
  176. {
  177. enum { value =
  178. has_value_type<T>::value
  179. & has_reference<T>::value
  180. & has_pointer<T>::value
  181. & has_difference_type<T>::value
  182. & has_iterator_category<T>::value
  183. };
  184. };
  185. BOOST_TT_AUX_BOOL_TRAIT_DEF1(
  186. is_full_iterator_traits,T,::boost::detail::is_full_iterator_traits_impl<T>::value)
  187. # ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
  188. BOOST_MPL_HAS_XXX_TRAIT_DEF(_Iterator_category)
  189. // is_stlport_40_debug_iterator --
  190. //
  191. // A metafunction returning true iff T has all the requisite nested
  192. // types to satisfy the requirements of an STLPort 4.0 debug iterator
  193. // iterator_traits implementation.
  194. template <class T>
  195. struct is_stlport_40_debug_iterator_impl
  196. {
  197. enum { value =
  198. has_value_type<T>::value
  199. & has_reference<T>::value
  200. & has_pointer<T>::value
  201. & has_difference_type<T>::value
  202. & has__Iterator_category<T>::value
  203. };
  204. };
  205. BOOST_TT_AUX_BOOL_TRAIT_DEF1(
  206. is_stlport_40_debug_iterator,T,::boost::detail::is_stlport_40_debug_iterator_impl<T>::value)
  207. template <class T>
  208. struct stlport_40_debug_iterator_traits
  209. {
  210. typedef typename T::value_type value_type;
  211. typedef typename T::reference reference;
  212. typedef typename T::pointer pointer;
  213. typedef typename T::difference_type difference_type;
  214. typedef typename T::_Iterator_category iterator_category;
  215. };
  216. # endif // BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
  217. template <class T> struct pointer_iterator_traits;
  218. # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  219. template <class T>
  220. struct pointer_iterator_traits<T*>
  221. {
  222. typedef typename remove_const<T>::type value_type;
  223. typedef T* pointer;
  224. typedef T& reference;
  225. typedef std::random_access_iterator_tag iterator_category;
  226. typedef std::ptrdiff_t difference_type;
  227. };
  228. # else
  229. // In case of no template partial specialization, and if T is a
  230. // pointer, iterator_traits<T>::value_type can still be computed. For
  231. // some basic types, remove_pointer is manually defined in
  232. // type_traits/broken_compiler_spec.hpp. For others, do it yourself.
  233. template<class P> class please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee;
  234. template<class P>
  235. struct pointer_value_type
  236. : mpl::if_<
  237. is_same<P, typename remove_pointer<P>::type>
  238. , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<P>
  239. , typename remove_const<
  240. typename remove_pointer<P>::type
  241. >::type
  242. >
  243. {
  244. };
  245. template<class P>
  246. struct pointer_reference
  247. : mpl::if_<
  248. is_same<P, typename remove_pointer<P>::type>
  249. , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<P>
  250. , typename remove_pointer<P>::type&
  251. >
  252. {
  253. };
  254. template <class T>
  255. struct pointer_iterator_traits
  256. {
  257. typedef T pointer;
  258. typedef std::random_access_iterator_tag iterator_category;
  259. typedef std::ptrdiff_t difference_type;
  260. typedef typename pointer_value_type<T>::type value_type;
  261. typedef typename pointer_reference<T>::type reference;
  262. };
  263. # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  264. // We'll sort iterator types into one of these classifications, from which we
  265. // can determine the difference_type, pointer, reference, and value_type
  266. template <class Iterator>
  267. struct standard_iterator_traits
  268. {
  269. typedef typename Iterator::difference_type difference_type;
  270. typedef typename Iterator::value_type value_type;
  271. typedef typename Iterator::pointer pointer;
  272. typedef typename Iterator::reference reference;
  273. typedef typename Iterator::iterator_category iterator_category;
  274. };
  275. template <class Iterator>
  276. struct msvc_stdlib_mutable_traits
  277. : std::iterator_traits<Iterator>
  278. {
  279. typedef typename std::iterator_traits<Iterator>::distance_type difference_type;
  280. typedef typename std::iterator_traits<Iterator>::value_type* pointer;
  281. typedef typename std::iterator_traits<Iterator>::value_type& reference;
  282. };
  283. template <class Iterator>
  284. struct msvc_stdlib_const_traits
  285. : std::iterator_traits<Iterator>
  286. {
  287. typedef typename std::iterator_traits<Iterator>::distance_type difference_type;
  288. typedef const typename std::iterator_traits<Iterator>::value_type* pointer;
  289. typedef const typename std::iterator_traits<Iterator>::value_type& reference;
  290. };
  291. # ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
  292. template <class Iterator>
  293. struct is_bad_output_iterator
  294. : is_base_and_derived<
  295. std::iterator<std::output_iterator_tag,void,void,void,void>
  296. , Iterator>
  297. {
  298. };
  299. struct bad_output_iterator_traits
  300. {
  301. typedef void value_type;
  302. typedef void difference_type;
  303. typedef std::output_iterator_tag iterator_category;
  304. typedef void pointer;
  305. typedef void reference;
  306. };
  307. # endif
  308. // If we're looking at an MSVC6 (old Dinkumware) ``standard''
  309. // iterator, this will generate an appropriate traits class.
  310. template <class Iterator>
  311. struct msvc_stdlib_iterator_traits
  312. : mpl::if_<
  313. is_mutable_iterator<Iterator>
  314. , msvc_stdlib_mutable_traits<Iterator>
  315. , msvc_stdlib_const_traits<Iterator>
  316. >::type
  317. {};
  318. template <class Iterator>
  319. struct non_pointer_iterator_traits
  320. : mpl::if_<
  321. // if the iterator contains all the right nested types...
  322. is_full_iterator_traits<Iterator>
  323. // Use a standard iterator_traits implementation
  324. , standard_iterator_traits<Iterator>
  325. # ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
  326. // Check for STLPort 4.0 broken _Iterator_category type
  327. , mpl::if_<
  328. is_stlport_40_debug_iterator<Iterator>
  329. , stlport_40_debug_iterator_traits<Iterator>
  330. # endif
  331. // Otherwise, assume it's a Dinkum iterator
  332. , msvc_stdlib_iterator_traits<Iterator>
  333. # ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
  334. >::type
  335. # endif
  336. >::type
  337. {
  338. };
  339. template <class Iterator>
  340. struct iterator_traits_aux
  341. : mpl::if_<
  342. is_pointer<Iterator>
  343. , pointer_iterator_traits<Iterator>
  344. , non_pointer_iterator_traits<Iterator>
  345. >::type
  346. {
  347. };
  348. template <class Iterator>
  349. struct iterator_traits
  350. {
  351. // Explicit forwarding from base class needed to keep MSVC6 happy
  352. // under some circumstances.
  353. private:
  354. # ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
  355. typedef
  356. typename mpl::if_<
  357. is_bad_output_iterator<Iterator>
  358. , bad_output_iterator_traits
  359. , iterator_traits_aux<Iterator>
  360. >::type base;
  361. # else
  362. typedef iterator_traits_aux<Iterator> base;
  363. # endif
  364. public:
  365. typedef typename base::value_type value_type;
  366. typedef typename base::pointer pointer;
  367. typedef typename base::reference reference;
  368. typedef typename base::difference_type difference_type;
  369. typedef typename base::iterator_category iterator_category;
  370. };
  371. // This specialization cuts off ETI (Early Template Instantiation) for MSVC.
  372. template <> struct iterator_traits<int>
  373. {
  374. typedef int value_type;
  375. typedef int pointer;
  376. typedef int reference;
  377. typedef int difference_type;
  378. typedef int iterator_category;
  379. };
  380. }} // namespace boost::detail
  381. # endif // workarounds
  382. namespace boost { namespace detail {
  383. namespace iterator_traits_
  384. {
  385. template <class Iterator, class Difference>
  386. struct distance_select
  387. {
  388. static Difference execute(Iterator i1, const Iterator i2, ...)
  389. {
  390. Difference result = 0;
  391. while (i1 != i2)
  392. {
  393. ++i1;
  394. ++result;
  395. }
  396. return result;
  397. }
  398. static Difference execute(Iterator i1, const Iterator i2, std::random_access_iterator_tag*)
  399. {
  400. return i2 - i1;
  401. }
  402. };
  403. } // namespace boost::detail::iterator_traits_
  404. template <class Iterator>
  405. inline typename iterator_traits<Iterator>::difference_type
  406. distance(Iterator first, Iterator last)
  407. {
  408. typedef typename iterator_traits<Iterator>::difference_type diff_t;
  409. typedef typename ::boost::detail::iterator_traits<Iterator>::iterator_category iterator_category;
  410. return iterator_traits_::distance_select<Iterator,diff_t>::execute(
  411. first, last, (iterator_category*)0);
  412. }
  413. }}
  414. # endif
  415. # undef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
  416. # undef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
  417. #endif // ITERATOR_DWA122600_HPP_