Line data Source code
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_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
8 : #define BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
9 :
10 : #include <iterator>
11 : #include <type_traits>
12 :
13 : #include <boost/core/use_default.hpp>
14 : #include <boost/core/empty_value.hpp>
15 : #include <boost/iterator/iterator_adaptor.hpp>
16 : #include <boost/iterator/enable_if_convertible.hpp>
17 : #include <boost/iterator/detail/eval_if_default.hpp>
18 :
19 : namespace boost {
20 : namespace iterators {
21 :
22 : template<
23 : typename UnaryFunction,
24 : typename Iterator,
25 : typename Reference = use_default,
26 : typename Value = use_default
27 : >
28 : class transform_iterator;
29 :
30 : namespace detail {
31 :
32 : template< typename UnaryFunc, typename Iterator >
33 : struct transform_iterator_default_reference
34 : {
35 : using type = decltype(std::declval< UnaryFunc const& >()(std::declval< typename std::iterator_traits< Iterator >::reference >()));
36 : };
37 :
38 : // Compute the iterator_adaptor instantiation to be used for transform_iterator
39 : template< typename UnaryFunc, typename Iterator, typename Reference, typename Value >
40 : struct transform_iterator_base
41 : {
42 : private:
43 : // By default, dereferencing the iterator yields the same as
44 : // the function.
45 : using reference = detail::eval_if_default_t<
46 : Reference,
47 : transform_iterator_default_reference< UnaryFunc, Iterator >
48 : >;
49 :
50 : // To get the default for Value: remove any reference on the
51 : // result type, but retain any constness to signal
52 : // non-writability. Note that if we adopt Thomas' suggestion
53 : // to key non-writability *only* on the Reference argument,
54 : // we'd need to strip constness here as well.
55 : using cv_value_type = detail::eval_if_default_t<
56 : Value,
57 : std::remove_reference< reference >
58 : >;
59 :
60 : public:
61 : using type = iterator_adaptor<
62 : transform_iterator< UnaryFunc, Iterator, Reference, Value >,
63 : Iterator,
64 : cv_value_type,
65 : use_default, // Leave the traversal category alone
66 : reference
67 : >;
68 : };
69 :
70 : } // namespace detail
71 :
72 : template< typename UnaryFunc, typename Iterator, typename Reference, typename Value >
73 : class transform_iterator :
74 : public detail::transform_iterator_base< UnaryFunc, Iterator, Reference, Value >::type,
75 : private boost::empty_value< UnaryFunc >
76 : {
77 : friend class iterator_core_access;
78 :
79 : private:
80 : using super_t = typename detail::transform_iterator_base< UnaryFunc, Iterator, Reference, Value >::type;
81 : using functor_base = boost::empty_value< UnaryFunc >;
82 :
83 : public:
84 : transform_iterator() = default;
85 :
86 2912 : transform_iterator(Iterator const& x, UnaryFunc f) :
87 1456 : super_t(x),
88 1456 : functor_base(boost::empty_init_t{}, f)
89 4368 : {}
90 :
91 : // don't provide this constructor if UnaryFunc is a
92 : // function pointer type, since it will be 0. Too dangerous.
93 : template< bool Requires = std::is_class< UnaryFunc >::value, typename = typename std::enable_if< Requires >::type >
94 : explicit transform_iterator(Iterator const& x) :
95 : super_t(x)
96 : {}
97 :
98 : template<
99 : typename OtherUnaryFunction,
100 : typename OtherIterator,
101 : typename OtherReference,
102 : typename OtherValue,
103 : typename = enable_if_convertible_t< OtherIterator, Iterator >,
104 : typename = enable_if_convertible_t< OtherUnaryFunction, UnaryFunc >
105 : >
106 : transform_iterator(transform_iterator< OtherUnaryFunction, OtherIterator, OtherReference, OtherValue > const& t) :
107 : super_t(t.base()),
108 : functor_base(boost::empty_init_t{}, t.functor())
109 : {}
110 :
111 : UnaryFunc functor() const { return functor_base::get(); }
112 :
113 : private:
114 4088 : typename super_t::reference dereference() const { return functor_base::get()(*this->base()); }
115 : };
116 :
117 : template< typename UnaryFunc, typename Iterator >
118 1456 : inline transform_iterator< UnaryFunc, Iterator > make_transform_iterator(Iterator it, UnaryFunc fun)
119 : {
120 1456 : return transform_iterator< UnaryFunc, Iterator >(it, fun);
121 : }
122 :
123 : // Version which allows explicit specification of the UnaryFunc
124 : // type.
125 : //
126 : // This generator is not provided if UnaryFunc is a function
127 : // pointer type, because it's too dangerous: the default-constructed
128 : // function pointer in the iterator be 0, leading to a runtime
129 : // crash.
130 : template< typename UnaryFunc, typename Iterator >
131 : inline typename std::enable_if<
132 : std::is_class< UnaryFunc >::value, // We should probably find a cheaper test than is_class<>
133 : transform_iterator< UnaryFunc, Iterator >
134 : >::type make_transform_iterator(Iterator it)
135 : {
136 : return transform_iterator< UnaryFunc, Iterator >(it);
137 : }
138 :
139 : } // namespace iterators
140 :
141 : using iterators::transform_iterator;
142 : using iterators::make_transform_iterator;
143 :
144 : } // namespace boost
145 :
146 : #endif // BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
|