Ticket #7597: transform_output_iterator.hpp

File transform_output_iterator.hpp, 4.9 KB (added by louis.dionne92@…, 10 years ago)

implementation

Line 
1// Copyright Louis Dionne 2012. Use, modification and distribution is subject
2// to the Boost Software License, Version 1.0. (See accompanying file
3// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5#ifndef BOOST_ITERATOR_TRANSFORM_OUTPUT_ITERATOR_HPP
6#define BOOST_ITERATOR_TRANSFORM_OUTPUT_ITERATOR_HPP
7
8#include <boost/iterator/iterator_categories.hpp>
9#include <boost/mpl/bool_fwd.hpp>
10#include <boost/mpl/eval_if.hpp>
11#include <boost/mpl/identity.hpp>
12#include <boost/mpl/not.hpp>
13#include <boost/utility/enable_if.hpp>
14
15
16namespace boost {
17
18template <typename Iterator> struct is_transform_output_iterator_type;
19
20template <typename UnaryFunction, typename Iterator>
21class transform_output_iterator {
22 UnaryFunction f_;
23 Iterator out_;
24
25 template <typename UnaryFunction_, typename Iterator_>
26 class output_proxy {
27 UnaryFunction_& f_;
28 Iterator_& out_;
29
30 public:
31 explicit output_proxy(UnaryFunction_& f, Iterator_& out)
32 : f_(f), out_(out)
33 { }
34
35 template <typename T>
36 output_proxy& operator=(T const& x) {
37 *out_ = f_(x);
38 return *this;
39 }
40 };
41
42 // Apply the append metafunction to a given type. This is only required
43 // for the eval_if construct below.
44 template <typename It, typename F>
45 struct apply_append {
46 typedef typename It::template append<F>::type type;
47 };
48
49 // Metafunction computing the type of a transform_output_iterator applying
50 // the G function after applying all the function it currently applies.
51 template <typename G>
52 struct append {
53 typedef transform_output_iterator<UnaryFunction,
54 typename mpl::eval_if<is_transform_output_iterator_type<Iterator>,
55 apply_append<Iterator, G>,
56 mpl::identity<transform_output_iterator<G, Iterator> >
57 >::type
58 > type;
59 };
60
61 // We need to friend all types of transform_output_iterator because we
62 // need to access the and_then_impl method of out_.
63 template <typename UnaryFunction_, typename Iterator_>
64 friend class transform_output_iterator;
65
66 template <typename G>
67 typename enable_if<is_transform_output_iterator_type<Iterator>,
68 typename append<G>::type>::type and_then_impl(G const& g) const {
69 return typename append<G>::type(f_, out_.and_then_impl(g));
70 }
71
72 template <typename G>
73 typename enable_if<mpl::not_<
74 is_transform_output_iterator_type<Iterator> >,
75 typename append<G>::type>::type and_then_impl(G const& g) const {
76 typedef transform_output_iterator<G, Iterator> last_type;
77 typedef transform_output_iterator<UnaryFunction, last_type>
78 before_last_type;
79 return before_last_type(f_, last_type(g, out_));
80 }
81
82public:
83 typedef void value_type;
84 typedef void reference;
85 typedef void pointer;
86 typedef void difference_type;
87 typedef incrementable_traversal_tag iterator_category;
88
89 template <typename G>
90 typename append<G>::type and_then(G const& g = G()) const {
91 return and_then_impl(g);
92 }
93
94 explicit transform_output_iterator(UnaryFunction const& f,
95 Iterator const& iterator)
96 : f_(f), out_(iterator)
97 { }
98
99 explicit transform_output_iterator(Iterator const& iterator)
100 : out_(iterator)
101 { }
102
103 transform_output_iterator& operator++() {
104 ++out_;
105 return *this;
106 }
107
108 transform_output_iterator operator++(int) {
109 transform_output_iterator tmp(*this);
110 ++out_;
111 return tmp;
112 }
113
114 output_proxy<UnaryFunction, Iterator> operator*() {
115 return output_proxy<UnaryFunction, Iterator>(f_, out_);
116 }
117
118 output_proxy<UnaryFunction const, Iterator const> operator*() const {
119 return output_proxy<UnaryFunction const, Iterator const>(f_, out_);
120 }
121};
122
123template <typename Iterator>
124struct is_transform_output_iterator_type
125 : mpl::false_
126{ };
127
128template <typename UnaryFunction, typename Iterator>
129struct is_transform_output_iterator_type<
130 transform_output_iterator<UnaryFunction, Iterator> >
131 : mpl::true_
132{ };
133
134template <typename Iterator>
135bool is_transform_output_iterator(Iterator const&) {
136 return ::boost::is_transform_output_iterator_type<Iterator>::value;
137}
138
139template <typename UnaryFunction, typename Iterator>
140transform_output_iterator<UnaryFunction, Iterator>
141make_transform_output_iterator(UnaryFunction const& f,
142 Iterator const& iterator) {
143 return transform_output_iterator<UnaryFunction, Iterator>(f, iterator);
144}
145
146template <typename UnaryFunction, typename Iterator>
147transform_output_iterator<UnaryFunction, Iterator>
148make_transform_output_iterator(Iterator const& iterator) {
149 return transform_output_iterator<UnaryFunction, Iterator>(iterator);
150}
151
152} // end namespace boost
153
154#endif // !BOOST_ITERATOR_TRANSFORM_OUTPUT_ITERATOR_HPP