transform_iterator.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // (C) Copyright David Abrahams 2002.
  2. // (C) Copyright Jeremy Siek 2002.
  3. // (C) Copyright Thomas Witt 2002.
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
  8. #define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
  9. #include <boost/function.hpp>
  10. #include <boost/iterator.hpp>
  11. #include <boost/iterator/detail/enable_if.hpp>
  12. #include <boost/iterator/iterator_adaptor.hpp>
  13. #include <boost/iterator/iterator_categories.hpp>
  14. #include <boost/mpl/not.hpp>
  15. #include <boost/mpl/bool.hpp>
  16. #include <boost/type_traits/function_traits.hpp>
  17. #include <boost/type_traits/is_const.hpp>
  18. #include <boost/type_traits/is_class.hpp>
  19. #include <boost/type_traits/is_function.hpp>
  20. #include <boost/type_traits/is_reference.hpp>
  21. #include <boost/type_traits/remove_const.hpp>
  22. #include <boost/type_traits/remove_reference.hpp>
  23. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
  24. # include <boost/type_traits/is_base_and_derived.hpp>
  25. #endif
  26. #include <boost/iterator/detail/config_def.hpp>
  27. namespace boost
  28. {
  29. template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
  30. class transform_iterator;
  31. namespace detail
  32. {
  33. template <class UnaryFunc>
  34. struct function_object_result
  35. {
  36. typedef typename UnaryFunc::result_type type;
  37. };
  38. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  39. template <class Return, class Argument>
  40. struct function_object_result<Return(*)(Argument)>
  41. {
  42. typedef Return type;
  43. };
  44. #endif
  45. // Compute the iterator_adaptor instantiation to be used for transform_iterator
  46. template <class UnaryFunc, class Iterator, class Reference, class Value>
  47. struct transform_iterator_base
  48. {
  49. private:
  50. // By default, dereferencing the iterator yields the same as
  51. // the function. Do we need to adjust the way
  52. // function_object_result is computed for the standard
  53. // proposal (e.g. using Doug's result_of)?
  54. typedef typename ia_dflt_help<
  55. Reference
  56. , function_object_result<UnaryFunc>
  57. >::type reference;
  58. // To get the default for Value: remove any reference on the
  59. // result type, but retain any constness to signal
  60. // non-writability. Note that if we adopt Thomas' suggestion
  61. // to key non-writability *only* on the Reference argument,
  62. // we'd need to strip constness here as well.
  63. typedef typename ia_dflt_help<
  64. Value
  65. , remove_reference<reference>
  66. >::type cv_value_type;
  67. public:
  68. typedef iterator_adaptor<
  69. transform_iterator<UnaryFunc, Iterator, Reference, Value>
  70. , Iterator
  71. , cv_value_type
  72. , use_default // Leave the traversal category alone
  73. , reference
  74. > type;
  75. };
  76. }
  77. template <class UnaryFunc, class Iterator, class Reference, class Value>
  78. class transform_iterator
  79. : public boost::detail::transform_iterator_base<UnaryFunc, Iterator, Reference, Value>::type
  80. {
  81. typedef typename
  82. boost::detail::transform_iterator_base<UnaryFunc, Iterator, Reference, Value>::type
  83. super_t;
  84. friend class iterator_core_access;
  85. public:
  86. transform_iterator() { }
  87. transform_iterator(Iterator const& x, UnaryFunc f)
  88. : super_t(x), m_f(f) { }
  89. explicit transform_iterator(Iterator const& x)
  90. : super_t(x)
  91. {
  92. // Pro8 is a little too aggressive about instantiating the
  93. // body of this function.
  94. #if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
  95. // don't provide this constructor if UnaryFunc is a
  96. // function pointer type, since it will be 0. Too dangerous.
  97. BOOST_STATIC_ASSERT(is_class<UnaryFunc>::value);
  98. #endif
  99. }
  100. template<
  101. class OtherUnaryFunction
  102. , class OtherIterator
  103. , class OtherReference
  104. , class OtherValue>
  105. transform_iterator(
  106. transform_iterator<OtherUnaryFunction, OtherIterator, OtherReference, OtherValue> const& t
  107. , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
  108. #if !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  109. , typename enable_if_convertible<OtherUnaryFunction, UnaryFunc>::type* = 0
  110. #endif
  111. )
  112. : super_t(t.base()), m_f(t.functor())
  113. {}
  114. UnaryFunc functor() const
  115. { return m_f; }
  116. private:
  117. typename super_t::reference dereference() const
  118. { return m_f(*this->base()); }
  119. // Probably should be the initial base class so it can be
  120. // optimized away via EBO if it is an empty class.
  121. UnaryFunc m_f;
  122. };
  123. template <class UnaryFunc, class Iterator>
  124. transform_iterator<UnaryFunc, Iterator>
  125. make_transform_iterator(Iterator it, UnaryFunc fun)
  126. {
  127. return transform_iterator<UnaryFunc, Iterator>(it, fun);
  128. }
  129. // Version which allows explicit specification of the UnaryFunc
  130. // type.
  131. //
  132. // This generator is not provided if UnaryFunc is a function
  133. // pointer type, because it's too dangerous: the default-constructed
  134. // function pointer in the iterator be 0, leading to a runtime
  135. // crash.
  136. template <class UnaryFunc, class Iterator>
  137. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  138. typename mpl::if_<
  139. #else
  140. typename iterators::enable_if<
  141. #endif
  142. is_class<UnaryFunc> // We should probably find a cheaper test than is_class<>
  143. , transform_iterator<UnaryFunc, Iterator>
  144. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  145. , int[3]
  146. #endif
  147. >::type
  148. make_transform_iterator(Iterator it)
  149. {
  150. return transform_iterator<UnaryFunc, Iterator>(it, UnaryFunc());
  151. }
  152. #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  153. template <class Return, class Argument, class Iterator>
  154. transform_iterator< Return (*)(Argument), Iterator, Return>
  155. make_transform_iterator(Iterator it, Return (*fun)(Argument))
  156. {
  157. return transform_iterator<Return (*)(Argument), Iterator, Return>(it, fun);
  158. }
  159. #endif
  160. } // namespace boost
  161. #include <boost/iterator/detail/config_undef.hpp>
  162. #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP