Ticket #7597: transform_output_iterator.2.hpp

File transform_output_iterator.2.hpp, 4.9 KB (added by Louis Dionne <louis.dionne92@…>, 10 years ago)

use disable_if<> instead of enable_if<not_<>>. Please use this one instead.

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