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_MAP_HPP
12 #define BOOST_RANGE_ADAPTOR_MAP_HPP
13 
14 #include <boost/range/adaptor/transformed.hpp>
15 #include <boost/range/iterator_range.hpp>
16 #include <boost/range/value_type.hpp>
17 #include <boost/range/reference.hpp>
18 #include <boost/range/concepts.hpp>
19 
20 namespace boost
21 {
22     namespace range_detail
23     {
24         struct map_keys_forwarder {};
25         struct map_values_forwarder {};
26 
27         template< class Map >
28         struct select_first
29         {
30             typedef BOOST_DEDUCED_TYPENAME range_reference<const Map>::type argument_type;
31             typedef const BOOST_DEDUCED_TYPENAME range_value<const Map>::type::first_type& result_type;
32 
operator ()boost::range_detail::select_first33             result_type operator()( argument_type r ) const
34             {
35                 return r.first;
36             }
37         };
38 
39         template< class Map >
40         struct select_second_mutable
41         {
42             typedef BOOST_DEDUCED_TYPENAME range_reference<Map>::type argument_type;
43             typedef BOOST_DEDUCED_TYPENAME range_value<Map>::type::second_type& result_type;
44 
operator ()boost::range_detail::select_second_mutable45             result_type operator()( argument_type r ) const
46             {
47                 return r.second;
48             }
49         };
50 
51         template< class Map >
52         struct select_second_const
53         {
54             typedef BOOST_DEDUCED_TYPENAME range_reference<const Map>::type argument_type;
55             typedef const BOOST_DEDUCED_TYPENAME range_value<const Map>::type::second_type& result_type;
56 
operator ()boost::range_detail::select_second_const57             result_type operator()( argument_type r ) const
58             {
59                 return r.second;
60             }
61         };
62 
63         template<class StdPairRng>
64         class select_first_range
65             : public transformed_range<
66                         select_first<StdPairRng>,
67                         const StdPairRng>
68         {
69             typedef transformed_range<select_first<StdPairRng>, const StdPairRng> base;
70         public:
71             typedef select_first<StdPairRng> transform_fn_type;
72             typedef const StdPairRng source_range_type;
73 
select_first_range(transform_fn_type fn,source_range_type & rng)74             select_first_range(transform_fn_type fn, source_range_type& rng)
75                 : base(fn, rng)
76             {
77             }
78 
select_first_range(const base & other)79             select_first_range(const base& other) : base(other) {}
80         };
81 
82         template<class StdPairRng>
83         class select_second_mutable_range
84             : public transformed_range<
85                         select_second_mutable<StdPairRng>,
86                         StdPairRng>
87         {
88             typedef transformed_range<select_second_mutable<StdPairRng>, StdPairRng> base;
89         public:
90             typedef select_second_mutable<StdPairRng> transform_fn_type;
91             typedef StdPairRng source_range_type;
92 
select_second_mutable_range(transform_fn_type fn,source_range_type & rng)93             select_second_mutable_range(transform_fn_type fn, source_range_type& rng)
94                 : base(fn, rng)
95             {
96             }
97 
select_second_mutable_range(const base & other)98             select_second_mutable_range(const base& other) : base(other) {}
99         };
100 
101         template<class StdPairRng>
102         class select_second_const_range
103             : public transformed_range<
104                         select_second_const<StdPairRng>,
105                         const StdPairRng>
106         {
107             typedef transformed_range<select_second_const<StdPairRng>, const StdPairRng> base;
108         public:
109             typedef select_second_const<StdPairRng> transform_fn_type;
110             typedef const StdPairRng source_range_type;
111 
select_second_const_range(transform_fn_type fn,source_range_type & rng)112             select_second_const_range(transform_fn_type fn, source_range_type& rng)
113                 : base(fn, rng)
114             {
115             }
116 
select_second_const_range(const base & other)117             select_second_const_range(const base& other) : base(other) {}
118         };
119 
120         template< class StdPairRng >
121         inline select_first_range<StdPairRng>
operator |(const StdPairRng & r,map_keys_forwarder)122         operator|( const StdPairRng& r, map_keys_forwarder )
123         {
124             BOOST_RANGE_CONCEPT_ASSERT((
125                 SinglePassRangeConcept<const StdPairRng>));
126 
127             return operator|( r,
128                 boost::adaptors::transformed( select_first<StdPairRng>() ) );
129         }
130 
131         template< class StdPairRng >
132         inline select_second_mutable_range<StdPairRng>
operator |(StdPairRng & r,map_values_forwarder)133         operator|( StdPairRng& r, map_values_forwarder )
134         {
135             BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<StdPairRng>));
136 
137             return operator|( r,
138                 boost::adaptors::transformed( select_second_mutable<StdPairRng>() ) );
139         }
140 
141         template< class StdPairRng >
142         inline select_second_const_range<StdPairRng>
operator |(const StdPairRng & r,map_values_forwarder)143         operator|( const StdPairRng& r, map_values_forwarder )
144         {
145             BOOST_RANGE_CONCEPT_ASSERT((
146                 SinglePassRangeConcept<const StdPairRng>));
147 
148             return operator|( r,
149                 boost::adaptors::transformed( select_second_const<StdPairRng>() ) );
150         }
151 
152     } // 'range_detail'
153 
154     using range_detail::select_first_range;
155     using range_detail::select_second_mutable_range;
156     using range_detail::select_second_const_range;
157 
158     namespace adaptors
159     {
160         namespace
161         {
162             const range_detail::map_keys_forwarder map_keys =
163                                             range_detail::map_keys_forwarder();
164 
165             const range_detail::map_values_forwarder map_values =
166                                            range_detail::map_values_forwarder();
167         }
168 
169         template<class StdPairRange>
170         inline select_first_range<StdPairRange>
keys(const StdPairRange & rng)171         keys(const StdPairRange& rng)
172         {
173             BOOST_RANGE_CONCEPT_ASSERT((
174                 SinglePassRangeConcept<const StdPairRange>));
175 
176             return select_first_range<StdPairRange>(
177                 range_detail::select_first<StdPairRange>(), rng );
178         }
179 
180         template<class StdPairRange>
181         inline select_second_const_range<StdPairRange>
values(const StdPairRange & rng)182         values(const StdPairRange& rng)
183         {
184             BOOST_RANGE_CONCEPT_ASSERT((
185                 SinglePassRangeConcept<const StdPairRange>));
186 
187             return select_second_const_range<StdPairRange>(
188                 range_detail::select_second_const<StdPairRange>(), rng );
189         }
190 
191         template<class StdPairRange>
192         inline select_second_mutable_range<StdPairRange>
values(StdPairRange & rng)193         values(StdPairRange& rng)
194         {
195             BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<StdPairRange>));
196 
197             return select_second_mutable_range<StdPairRange>(
198                 range_detail::select_second_mutable<StdPairRange>(), rng );
199         }
200     } // 'adaptors'
201 
202 }
203 
204 #endif
205