source: NonGTP/Boost/boost/iterator/transform_iterator.hpp @ 857

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