any_iterator.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // Boost.Range library
  2. //
  3. // Copyright Neil Groves 2010. Use, modification and
  4. // distribution is subject to the Boost Software License, Version
  5. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see http://www.boost.org/libs/range/
  9. //
  10. #ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED
  11. #define BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED
  12. #include <boost/mpl/and.hpp>
  13. #include <boost/mpl/or.hpp>
  14. #include <boost/mpl/not.hpp>
  15. #include <boost/iterator/iterator_facade.hpp>
  16. #include <boost/type_traits/is_const.hpp>
  17. #include <boost/type_traits/is_reference.hpp>
  18. #include <boost/type_traits/remove_reference.hpp>
  19. #include <boost/range/detail/any_iterator_buffer.hpp>
  20. #include <boost/range/detail/any_iterator_interface.hpp>
  21. #include <boost/range/detail/any_iterator_wrapper.hpp>
  22. #include <boost/utility/enable_if.hpp>
  23. namespace boost
  24. {
  25. namespace range_detail
  26. {
  27. // metafunction to determine if T is a const reference
  28. template<class T>
  29. struct is_const_reference
  30. {
  31. typedef typename mpl::and_<
  32. typename is_reference<T>::type,
  33. typename is_const<
  34. typename remove_reference<T>::type
  35. >::type
  36. >::type type;
  37. };
  38. // metafunction to determine if T is a mutable reference
  39. template<class T>
  40. struct is_mutable_reference
  41. {
  42. typedef typename mpl::and_<
  43. typename is_reference<T>::type,
  44. typename mpl::not_<
  45. typename is_const<
  46. typename remove_reference<T>::type
  47. >::type
  48. >::type
  49. >::type type;
  50. };
  51. // metafunction to evaluate if a source 'reference' can be
  52. // converted to a target 'reference' as a value.
  53. //
  54. // This is true, when the target reference type is actually
  55. // not a reference, and the source reference is convertible
  56. // to the target type.
  57. template<class SourceReference, class TargetReference>
  58. struct is_convertible_to_value_as_reference
  59. {
  60. typedef typename mpl::and_<
  61. typename mpl::not_<
  62. typename is_reference<TargetReference>::type
  63. >::type
  64. , typename is_convertible<
  65. SourceReference
  66. , TargetReference
  67. >::type
  68. >::type type;
  69. };
  70. template<
  71. class Value
  72. , class Traversal
  73. , class Reference
  74. , class Difference
  75. , class Buffer = any_iterator_default_buffer
  76. >
  77. class any_iterator;
  78. // metafunction to determine if SomeIterator is an
  79. // any_iterator.
  80. //
  81. // This is the general implementation which evaluates to false.
  82. template<class SomeIterator>
  83. struct is_any_iterator
  84. : mpl::bool_<false>
  85. {
  86. };
  87. // specialization of is_any_iterator to return true for
  88. // any_iterator classes regardless of template parameters.
  89. template<
  90. class Value
  91. , class Traversal
  92. , class Reference
  93. , class Difference
  94. , class Buffer
  95. >
  96. struct is_any_iterator<
  97. any_iterator<
  98. Value
  99. , Traversal
  100. , Reference
  101. , Difference
  102. , Buffer
  103. >
  104. >
  105. : mpl::bool_<true>
  106. {
  107. };
  108. } // namespace range_detail
  109. namespace iterators
  110. {
  111. namespace detail
  112. {
  113. // Rationale:
  114. // These are specialized since the iterator_facade versions lack
  115. // the requisite typedefs to allow wrapping to determine the types
  116. // if a user copy constructs from a postfix increment.
  117. template<
  118. class Value
  119. , class Traversal
  120. , class Reference
  121. , class Difference
  122. , class Buffer
  123. >
  124. class postfix_increment_proxy<
  125. range_detail::any_iterator<
  126. Value
  127. , Traversal
  128. , Reference
  129. , Difference
  130. , Buffer
  131. >
  132. >
  133. {
  134. typedef range_detail::any_iterator<
  135. Value
  136. , Traversal
  137. , Reference
  138. , Difference
  139. , Buffer
  140. > any_iterator_type;
  141. public:
  142. typedef Value value_type;
  143. typedef typename std::iterator_traits<any_iterator_type>::iterator_category iterator_category;
  144. typedef Difference difference_type;
  145. typedef typename iterator_pointer<any_iterator_type>::type pointer;
  146. typedef Reference reference;
  147. explicit postfix_increment_proxy(any_iterator_type const& x)
  148. : stored_value(*x)
  149. {}
  150. value_type&
  151. operator*() const
  152. {
  153. return this->stored_value;
  154. }
  155. private:
  156. mutable value_type stored_value;
  157. };
  158. template<
  159. class Value
  160. , class Traversal
  161. , class Reference
  162. , class Difference
  163. , class Buffer
  164. >
  165. class writable_postfix_increment_proxy<
  166. range_detail::any_iterator<
  167. Value
  168. , Traversal
  169. , Reference
  170. , Difference
  171. , Buffer
  172. >
  173. >
  174. {
  175. typedef range_detail::any_iterator<
  176. Value
  177. , Traversal
  178. , Reference
  179. , Difference
  180. , Buffer
  181. > any_iterator_type;
  182. public:
  183. typedef Value value_type;
  184. typedef typename std::iterator_traits<any_iterator_type>::iterator_category iterator_category;
  185. typedef Difference difference_type;
  186. typedef typename iterator_pointer<any_iterator_type>::type pointer;
  187. typedef Reference reference;
  188. explicit writable_postfix_increment_proxy(any_iterator_type const& x)
  189. : stored_value(*x)
  190. , stored_iterator(x)
  191. {}
  192. // Dereferencing must return a proxy so that both *r++ = o and
  193. // value_type(*r++) can work. In this case, *r is the same as
  194. // *r++, and the conversion operator below is used to ensure
  195. // readability.
  196. writable_postfix_increment_proxy const&
  197. operator*() const
  198. {
  199. return *this;
  200. }
  201. // Provides readability of *r++
  202. operator value_type&() const
  203. {
  204. return stored_value;
  205. }
  206. // Provides writability of *r++
  207. template <class T>
  208. T const& operator=(T const& x) const
  209. {
  210. *this->stored_iterator = x;
  211. return x;
  212. }
  213. // This overload just in case only non-const objects are writable
  214. template <class T>
  215. T& operator=(T& x) const
  216. {
  217. *this->stored_iterator = x;
  218. return x;
  219. }
  220. // Provides X(r++)
  221. operator any_iterator_type const&() const
  222. {
  223. return stored_iterator;
  224. }
  225. private:
  226. mutable value_type stored_value;
  227. any_iterator_type stored_iterator;
  228. };
  229. } //namespace detail
  230. } //namespace iterators
  231. namespace range_detail
  232. {
  233. template<
  234. class Value
  235. , class Traversal
  236. , class Reference
  237. , class Difference
  238. , class Buffer
  239. >
  240. class any_iterator
  241. : public iterator_facade<
  242. any_iterator<
  243. Value
  244. , Traversal
  245. , Reference
  246. , Difference
  247. , Buffer
  248. >
  249. , Value
  250. , Traversal
  251. , Reference
  252. , Difference
  253. >
  254. {
  255. template<
  256. class OtherValue
  257. , class OtherTraversal
  258. , class OtherReference
  259. , class OtherDifference
  260. , class OtherBuffer
  261. >
  262. friend class any_iterator;
  263. struct enabler {};
  264. struct disabler {};
  265. typedef typename any_iterator_interface_type_generator<
  266. Traversal
  267. , Reference
  268. , Difference
  269. , Buffer
  270. >::type abstract_base_type;
  271. typedef iterator_facade<
  272. any_iterator<
  273. Value
  274. , Traversal
  275. , Reference
  276. , Difference
  277. , Buffer
  278. >
  279. , Value
  280. , Traversal
  281. , Reference
  282. , Difference
  283. > base_type;
  284. typedef Buffer buffer_type;
  285. public:
  286. typedef typename base_type::value_type value_type;
  287. typedef typename base_type::reference reference;
  288. typedef typename base_type::difference_type difference_type;
  289. // Default constructor
  290. any_iterator()
  291. : m_impl(0) {}
  292. // Simple copy construction without conversion
  293. any_iterator(const any_iterator& other)
  294. : base_type(other)
  295. , m_impl(other.m_impl
  296. ? other.m_impl->clone(m_buffer)
  297. : 0)
  298. {
  299. }
  300. // Simple assignment operator without conversion
  301. any_iterator& operator=(const any_iterator& other)
  302. {
  303. if (this != &other)
  304. {
  305. if (m_impl)
  306. m_impl->~abstract_base_type();
  307. m_buffer.deallocate();
  308. m_impl = 0;
  309. if (other.m_impl)
  310. m_impl = other.m_impl->clone(m_buffer);
  311. }
  312. return *this;
  313. }
  314. // Implicit conversion from another any_iterator where the
  315. // conversion is from a non-const reference to a const reference
  316. template<
  317. class OtherValue
  318. , class OtherTraversal
  319. , class OtherReference
  320. , class OtherDifference
  321. >
  322. any_iterator(const any_iterator<
  323. OtherValue,
  324. OtherTraversal,
  325. OtherReference,
  326. OtherDifference,
  327. Buffer
  328. >& other,
  329. typename ::boost::enable_if<
  330. typename mpl::and_<
  331. typename is_mutable_reference<OtherReference>::type,
  332. typename is_const_reference<Reference>::type
  333. >::type,
  334. enabler
  335. >::type* = 0
  336. )
  337. : m_impl(other.m_impl
  338. ? other.m_impl->clone_const_ref(m_buffer)
  339. : 0
  340. )
  341. {
  342. }
  343. // Implicit conversion from another any_iterator where the
  344. // reference types of the source and the target are references
  345. // that are either both const, or both non-const.
  346. template<
  347. class OtherValue
  348. , class OtherTraversal
  349. , class OtherReference
  350. , class OtherDifference
  351. >
  352. any_iterator(const any_iterator<
  353. OtherValue
  354. , OtherTraversal
  355. , OtherReference
  356. , OtherDifference
  357. , Buffer
  358. >& other,
  359. typename ::boost::enable_if<
  360. typename mpl::or_<
  361. typename mpl::and_<
  362. typename is_mutable_reference<OtherReference>::type,
  363. typename is_mutable_reference<Reference>::type
  364. >::type,
  365. typename mpl::and_<
  366. typename is_const_reference<OtherReference>::type,
  367. typename is_const_reference<Reference>::type
  368. >::type
  369. >::type,
  370. enabler
  371. >::type* = 0
  372. )
  373. : m_impl(other.m_impl
  374. ? other.m_impl->clone(m_buffer)
  375. : 0
  376. )
  377. {
  378. }
  379. // Implicit conversion to an any_iterator that uses a value for
  380. // the reference type.
  381. template<
  382. class OtherValue
  383. , class OtherTraversal
  384. , class OtherReference
  385. , class OtherDifference
  386. >
  387. any_iterator(const any_iterator<
  388. OtherValue
  389. , OtherTraversal
  390. , OtherReference
  391. , OtherDifference
  392. , Buffer
  393. >& other,
  394. typename ::boost::enable_if<
  395. typename is_convertible_to_value_as_reference<
  396. OtherReference
  397. , Reference
  398. >::type,
  399. enabler
  400. >::type* = 0
  401. )
  402. : m_impl(other.m_impl
  403. ? other.m_impl->clone_reference_as_value(m_buffer)
  404. : 0
  405. )
  406. {
  407. }
  408. any_iterator clone() const
  409. {
  410. any_iterator result;
  411. if (m_impl)
  412. result.m_impl = m_impl->clone(result.m_buffer);
  413. return result;
  414. }
  415. any_iterator<
  416. Value
  417. , Traversal
  418. , typename abstract_base_type::const_reference
  419. , Difference
  420. , Buffer
  421. >
  422. clone_const_ref() const
  423. {
  424. typedef any_iterator<
  425. Value
  426. , Traversal
  427. , typename abstract_base_type::const_reference
  428. , Difference
  429. , Buffer
  430. > result_type;
  431. result_type result;
  432. if (m_impl)
  433. result.m_impl = m_impl->clone_const_ref(result.m_buffer);
  434. return result;
  435. }
  436. // implicit conversion and construction from type-erasure-compatible
  437. // iterators
  438. template<class WrappedIterator>
  439. explicit any_iterator(
  440. const WrappedIterator& wrapped_iterator,
  441. typename disable_if<
  442. typename is_any_iterator<WrappedIterator>::type
  443. , disabler
  444. >::type* = 0
  445. )
  446. {
  447. typedef typename any_iterator_wrapper_type_generator<
  448. WrappedIterator
  449. , Traversal
  450. , Reference
  451. , Difference
  452. , Buffer
  453. >::type wrapper_type;
  454. void* ptr = m_buffer.allocate(sizeof(wrapper_type));
  455. m_impl = new(ptr) wrapper_type(wrapped_iterator);
  456. }
  457. ~any_iterator()
  458. {
  459. // manually run the destructor, the deallocation is automatically
  460. // handled by the any_iterator_small_buffer base class.
  461. if (m_impl)
  462. m_impl->~abstract_base_type();
  463. }
  464. private:
  465. friend class ::boost::iterator_core_access;
  466. Reference dereference() const
  467. {
  468. BOOST_ASSERT( m_impl );
  469. return m_impl->dereference();
  470. }
  471. bool equal(const any_iterator& other) const
  472. {
  473. return (m_impl == other.m_impl)
  474. || (m_impl && other.m_impl && m_impl->equal(*other.m_impl));
  475. }
  476. void increment()
  477. {
  478. BOOST_ASSERT( m_impl );
  479. m_impl->increment();
  480. }
  481. void decrement()
  482. {
  483. BOOST_ASSERT( m_impl );
  484. m_impl->decrement();
  485. }
  486. Difference distance_to(const any_iterator& other) const
  487. {
  488. return m_impl && other.m_impl
  489. ? m_impl->distance_to(*other.m_impl)
  490. : 0;
  491. }
  492. void advance(Difference offset)
  493. {
  494. BOOST_ASSERT( m_impl );
  495. m_impl->advance(offset);
  496. }
  497. any_iterator& swap(any_iterator& other)
  498. {
  499. BOOST_ASSERT( this != &other );
  500. // grab a temporary copy of the other iterator
  501. any_iterator tmp(other);
  502. // deallocate the other iterator, taking care to obey the
  503. // class-invariants in-case of exceptions later
  504. if (other.m_impl)
  505. {
  506. other.m_impl->~abstract_base_type();
  507. other.m_buffer.deallocate();
  508. other.m_impl = 0;
  509. }
  510. // If this is a non-null iterator then we need to put
  511. // a clone of this iterators implementation into the other
  512. // iterator.
  513. // We can't just swap because of the small buffer optimization.
  514. if (m_impl)
  515. {
  516. other.m_impl = m_impl->clone(other.m_buffer);
  517. m_impl->~abstract_base_type();
  518. m_buffer.deallocate();
  519. m_impl = 0;
  520. }
  521. // assign to this instance a clone of the temporarily held
  522. // tmp which represents the input other parameter at the
  523. // start of execution of this function.
  524. if (tmp.m_impl)
  525. m_impl = tmp.m_impl->clone(m_buffer);
  526. return *this;
  527. }
  528. buffer_type m_buffer;
  529. abstract_base_type* m_impl;
  530. };
  531. } // namespace range_detail
  532. } // namespace boost
  533. #endif // include guard