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 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 #include <boost/utility/result_of.hpp> 24 25 26 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) 27 # include <boost/type_traits/is_base_and_derived.hpp> 28 29 #endif 30 #include <boost/iterator/detail/config_def.hpp> 31 32 33 namespace boost { 34 namespace iterators { 35 36 template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default> 37 class transform_iterator; 38 39 namespace detail 40 { 41 // Compute the iterator_adaptor instantiation to be used for transform_iterator 42 template <class UnaryFunc, class Iterator, class Reference, class Value> 43 struct transform_iterator_base 44 { 45 private: 46 // By default, dereferencing the iterator yields the same as 47 // the function. 48 typedef typename ia_dflt_help< 49 Reference 50 , result_of<const UnaryFunc(typename std::iterator_traits<Iterator>::reference)> 51 >::type reference; 52 53 // To get the default for Value: remove any reference on the 54 // result type, but retain any constness to signal 55 // non-writability. Note that if we adopt Thomas' suggestion 56 // to key non-writability *only* on the Reference argument, 57 // we'd need to strip constness here as well. 58 typedef typename ia_dflt_help< 59 Value 60 , remove_reference<reference> 61 >::type cv_value_type; 62 63 public: 64 typedef iterator_adaptor< 65 transform_iterator<UnaryFunc, Iterator, Reference, Value> 66 , Iterator 67 , cv_value_type 68 , use_default // Leave the traversal category alone 69 , reference 70 > type; 71 }; 72 } 73 74 template <class UnaryFunc, class Iterator, class Reference, class Value> 75 class transform_iterator 76 : public boost::iterators::detail::transform_iterator_base<UnaryFunc, Iterator, Reference, Value>::type 77 { 78 typedef typename 79 boost::iterators::detail::transform_iterator_base<UnaryFunc, Iterator, Reference, Value>::type 80 super_t; 81 82 friend class iterator_core_access; 83 84 public: transform_iterator()85 transform_iterator() { } 86 transform_iterator(Iterator const & x,UnaryFunc f)87 transform_iterator(Iterator const& x, UnaryFunc f) 88 : super_t(x), m_f(f) { } 89 transform_iterator(Iterator const & x)90 explicit transform_iterator(Iterator const& x) 91 : super_t(x) 92 { 93 // Pro8 is a little too aggressive about instantiating the 94 // body of this function. 95 #if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) 96 // don't provide this constructor if UnaryFunc is a 97 // function pointer type, since it will be 0. Too dangerous. 98 BOOST_STATIC_ASSERT(is_class<UnaryFunc>::value); 99 #endif 100 } 101 102 template < 103 class OtherUnaryFunction 104 , class OtherIterator 105 , class OtherReference 106 , class OtherValue> transform_iterator(transform_iterator<OtherUnaryFunction,OtherIterator,OtherReference,OtherValue> const & t,typename enable_if_convertible<OtherIterator,Iterator>::type * =0,typename enable_if_convertible<OtherUnaryFunction,UnaryFunc>::type * =0)107 transform_iterator( 108 transform_iterator<OtherUnaryFunction, OtherIterator, OtherReference, OtherValue> const& t 109 , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 110 #if !BOOST_WORKAROUND(BOOST_MSVC, == 1310) 111 , typename enable_if_convertible<OtherUnaryFunction, UnaryFunc>::type* = 0 112 #endif 113 ) 114 : super_t(t.base()), m_f(t.functor()) 115 {} 116 functor() const117 UnaryFunc functor() const 118 { return m_f; } 119 120 private: dereference() const121 typename super_t::reference dereference() const 122 { return m_f(*this->base()); } 123 124 // Probably should be the initial base class so it can be 125 // optimized away via EBO if it is an empty class. 126 UnaryFunc m_f; 127 }; 128 129 template <class UnaryFunc, class Iterator> 130 inline transform_iterator<UnaryFunc, Iterator> make_transform_iterator(Iterator it,UnaryFunc fun)131 make_transform_iterator(Iterator it, UnaryFunc fun) 132 { 133 return transform_iterator<UnaryFunc, Iterator>(it, fun); 134 } 135 136 // Version which allows explicit specification of the UnaryFunc 137 // type. 138 // 139 // This generator is not provided if UnaryFunc is a function 140 // pointer type, because it's too dangerous: the default-constructed 141 // function pointer in the iterator be 0, leading to a runtime 142 // crash. 143 template <class UnaryFunc, class Iterator> 144 inline typename iterators::enable_if< 145 is_class<UnaryFunc> // We should probably find a cheaper test than is_class<> 146 , transform_iterator<UnaryFunc, Iterator> 147 >::type make_transform_iterator(Iterator it)148 make_transform_iterator(Iterator it) 149 { 150 return transform_iterator<UnaryFunc, Iterator>(it, UnaryFunc()); 151 } 152 153 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) 154 template <class Return, class Argument, class Iterator> 155 inline transform_iterator< Return (*)(Argument), Iterator, Return> make_transform_iterator(Iterator it,Return (* fun)(Argument))156 make_transform_iterator(Iterator it, Return (*fun)(Argument)) 157 { 158 return transform_iterator<Return (*)(Argument), Iterator, Return>(it, fun); 159 } 160 #endif 161 162 } // namespace iterators 163 164 using iterators::transform_iterator; 165 using iterators::make_transform_iterator; 166 167 } // namespace boost 168 169 #include <boost/iterator/detail/config_undef.hpp> 170 171 #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP 172