1 | // Boost.Range library |
2 | // |
3 | // Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and |
4 | // distribution is subject to the Boost Software License, Version |
5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | // |
8 | // For more information, see http://www.boost.org/libs/range/ |
9 | // |
10 | |
11 | #ifndef BOOST_RANGE_ADAPTOR_TRANSFORMED_HPP |
12 | #define BOOST_RANGE_ADAPTOR_TRANSFORMED_HPP |
13 | |
14 | #include <boost/range/adaptor/argument_fwd.hpp> |
15 | #include <boost/range/detail/default_constructible_unary_fn.hpp> |
16 | #include <boost/range/iterator_range.hpp> |
17 | #include <boost/range/concepts.hpp> |
18 | #include <boost/iterator/transform_iterator.hpp> |
19 | #include <boost/utility/result_of.hpp> |
20 | |
21 | namespace boost |
22 | { |
23 | namespace range_detail |
24 | { |
25 | // A type generator to produce the transform_iterator type conditionally |
26 | // including a wrapped predicate as appropriate. |
27 | template<typename P, typename It> |
28 | struct transform_iterator_gen |
29 | { |
30 | typedef transform_iterator< |
31 | typename default_constructible_unary_fn_gen< |
32 | P, |
33 | typename transform_iterator<P, It>::reference |
34 | >::type, |
35 | It |
36 | > type; |
37 | }; |
38 | |
39 | template< class F, class R > |
40 | struct transformed_range : |
41 | public boost::iterator_range< |
42 | typename transform_iterator_gen< |
43 | F, typename range_iterator<R>::type>::type> |
44 | { |
45 | private: |
46 | typedef typename transform_iterator_gen< |
47 | F, typename range_iterator<R>::type>::type transform_iter_t; |
48 | |
49 | typedef boost::iterator_range<transform_iter_t> base; |
50 | |
51 | public: |
52 | typedef typename default_constructible_unary_fn_gen< |
53 | F, |
54 | typename transform_iterator< |
55 | F, |
56 | typename range_iterator<R>::type |
57 | >::reference |
58 | >::type transform_fn_type; |
59 | |
60 | typedef R source_range_type; |
61 | |
62 | transformed_range(transform_fn_type f, R& r) |
63 | : base(transform_iter_t(boost::begin(r), f), |
64 | transform_iter_t(boost::end(r), f)) |
65 | { |
66 | } |
67 | }; |
68 | |
69 | template< class T > |
70 | struct transform_holder : holder<T> |
71 | { |
72 | transform_holder( T r ) : holder<T>(r) |
73 | { |
74 | } |
75 | }; |
76 | |
77 | template< class SinglePassRange, class UnaryFunction > |
78 | inline transformed_range<UnaryFunction,SinglePassRange> |
79 | operator|( SinglePassRange& r, |
80 | const transform_holder<UnaryFunction>& f ) |
81 | { |
82 | BOOST_RANGE_CONCEPT_ASSERT(( |
83 | SinglePassRangeConcept<SinglePassRange>)); |
84 | |
85 | return transformed_range<UnaryFunction,SinglePassRange>( f.val, r ); |
86 | } |
87 | |
88 | template< class SinglePassRange, class UnaryFunction > |
89 | inline transformed_range<UnaryFunction, const SinglePassRange> |
90 | operator|( const SinglePassRange& r, |
91 | const transform_holder<UnaryFunction>& f ) |
92 | { |
93 | BOOST_RANGE_CONCEPT_ASSERT(( |
94 | SinglePassRangeConcept<const SinglePassRange>)); |
95 | |
96 | return transformed_range<UnaryFunction, const SinglePassRange>( |
97 | f.val, r); |
98 | } |
99 | |
100 | } // 'range_detail' |
101 | |
102 | using range_detail::transformed_range; |
103 | |
104 | namespace adaptors |
105 | { |
106 | namespace |
107 | { |
108 | const range_detail::forwarder<range_detail::transform_holder> |
109 | transformed = |
110 | range_detail::forwarder<range_detail::transform_holder>(); |
111 | } |
112 | |
113 | template<class UnaryFunction, class SinglePassRange> |
114 | inline transformed_range<UnaryFunction, SinglePassRange> |
115 | transform(SinglePassRange& rng, UnaryFunction fn) |
116 | { |
117 | BOOST_RANGE_CONCEPT_ASSERT(( |
118 | SinglePassRangeConcept<SinglePassRange>)); |
119 | |
120 | return transformed_range<UnaryFunction, SinglePassRange>(fn, rng); |
121 | } |
122 | |
123 | template<class UnaryFunction, class SinglePassRange> |
124 | inline transformed_range<UnaryFunction, const SinglePassRange> |
125 | transform(const SinglePassRange& rng, UnaryFunction fn) |
126 | { |
127 | BOOST_RANGE_CONCEPT_ASSERT(( |
128 | SinglePassRangeConcept<const SinglePassRange>)); |
129 | |
130 | return transformed_range<UnaryFunction, const SinglePassRange>( |
131 | fn, rng); |
132 | } |
133 | } // 'adaptors' |
134 | |
135 | } |
136 | |
137 | #endif |
138 | |