]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/x3/support/traits/container_traits.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / support / traits / container_traits.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 http://spirit.sourceforge.net/
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM)
10 #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM
11
12 #include <boost/fusion/support/category_of.hpp>
13 #include <boost/spirit/home/x3/support/unused.hpp>
14 #include <boost/fusion/include/deque.hpp>
15 #include <boost/mpl/identity.hpp>
16 #include <boost/type_traits/make_void.hpp>
17
18 #include <vector>
19 #include <string>
20 #include <iterator>
21 #include <algorithm>
22
23 namespace boost { namespace spirit { namespace x3 { namespace traits
24 {
25 ///////////////////////////////////////////////////////////////////////////
26 // This file contains some container utils for stl containers.
27 ///////////////////////////////////////////////////////////////////////////
28
29 namespace detail
30 {
31 template <typename T, typename Enabler = void>
32 struct is_container_impl : mpl::false_ {};
33
34 template <typename T>
35 struct is_container_impl<T, void_t<
36 typename T::value_type, typename T::iterator,
37 typename T::size_type, typename T::reference> > : mpl::true_ {};
38
39 template <typename T, typename Enabler = void>
40 struct is_associative_impl : mpl::false_ {};
41
42 template <typename T>
43 struct is_associative_impl<T, void_t<typename T::key_type>>
44 : mpl::true_ {};
45 }
46
47 template <typename T>
48 using is_container = typename detail::is_container_impl<T>::type;
49
50 template <typename T>
51 using is_associative = typename detail::is_associative_impl<T>::type;
52
53 ///////////////////////////////////////////////////////////////////////////
54 namespace detail
55 {
56 template <typename T>
57 struct remove_value_const : mpl::identity<T> {};
58
59 template <typename T>
60 struct remove_value_const<T const> : remove_value_const<T> {};
61
62 template <typename F, typename S>
63 struct remove_value_const<std::pair<F, S>>
64 {
65 typedef typename remove_value_const<F>::type first_type;
66 typedef typename remove_value_const<S>::type second_type;
67 typedef std::pair<first_type, second_type> type;
68 };
69 }
70
71 ///////////////////////////////////////////////////////////////////////
72 template <typename Container, typename Enable = void>
73 struct container_value
74 : detail::remove_value_const<typename Container::value_type>
75 {};
76
77 template <typename Container>
78 struct container_value<Container const> : container_value<Container> {};
79
80 // There is no single container value for fusion maps, but because output
81 // of this metafunc is used to check wheter parser's attribute can be
82 // saved to container, we simply return whole fusion::map as is
83 // so that check can be done in traits::is_substitute specialisation
84 template <typename T>
85 struct container_value<T
86 , typename enable_if<typename mpl::eval_if <
87 fusion::traits::is_sequence<T>
88 , fusion::traits::is_associative<T>
89 , mpl::false_ >::type >::type>
90 : mpl::identity<T> {};
91
92 template <>
93 struct container_value<unused_type> : mpl::identity<unused_type> {};
94
95 ///////////////////////////////////////////////////////////////////////////
96 template <typename Container, typename Enable = void>
97 struct container_iterator
98 : mpl::identity<typename Container::iterator> {};
99
100 template <typename Container>
101 struct container_iterator<Container const>
102 : mpl::identity<typename Container::const_iterator> {};
103
104 template <>
105 struct container_iterator<unused_type>
106 : mpl::identity<unused_type const*> {};
107
108 template <>
109 struct container_iterator<unused_type const>
110 : mpl::identity<unused_type const*> {};
111
112 ///////////////////////////////////////////////////////////////////////////
113 template <typename Container, typename T>
114 bool push_back(Container& c, T&& val);
115
116 template <typename Container, typename Enable = void>
117 struct push_back_container
118 {
119 template <typename T>
120 static bool call(Container& c, T&& val)
121 {
122 c.insert(c.end(), static_cast<T&&>(val));
123 return true;
124 }
125 };
126
127 template <typename Container, typename T>
128 inline bool push_back(Container& c, T&& val)
129 {
130 return push_back_container<Container>::call(c, static_cast<T&&>(val));
131 }
132
133 template <typename Container>
134 inline bool push_back(Container&, unused_type)
135 {
136 return true;
137 }
138
139 template <typename T>
140 inline bool push_back(unused_type, T&&)
141 {
142 return true;
143 }
144
145 inline bool push_back(unused_type, unused_type)
146 {
147 return true;
148 }
149
150 ///////////////////////////////////////////////////////////////////////////
151 template <typename Container, typename Iterator>
152 bool append(Container& c, Iterator first, Iterator last);
153
154 template <typename Container, typename Enable = void>
155 struct append_container
156 {
157 private:
158 template <typename Iterator>
159 static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
160 {
161 c.insert(c.end(), first, last);
162 }
163
164 template <typename Iterator>
165 static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
166 {
167 c.insert(first, last);
168 }
169
170 public:
171 template <typename Iterator>
172 static bool call(Container& c, Iterator first, Iterator last)
173 {
174 insert(c, first, last, is_associative<Container>{});
175 return true;
176 }
177 };
178
179 template <typename Container, typename Iterator>
180 inline bool append(Container& c, Iterator first, Iterator last)
181 {
182 return append_container<Container>::call(c, first, last);
183 }
184
185 template <typename Iterator>
186 inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
187 {
188 return true;
189 }
190
191 ///////////////////////////////////////////////////////////////////////////
192 template <typename Container, typename Enable = void>
193 struct is_empty_container
194 {
195 static bool call(Container const& c)
196 {
197 return c.empty();
198 }
199 };
200
201 template <typename Container>
202 inline bool is_empty(Container const& c)
203 {
204 return is_empty_container<Container>::call(c);
205 }
206
207 inline bool is_empty(unused_type)
208 {
209 return true;
210 }
211
212 ///////////////////////////////////////////////////////////////////////////
213 template <typename Container, typename Enable = void>
214 struct begin_container
215 {
216 static typename container_iterator<Container>::type call(Container& c)
217 {
218 return c.begin();
219 }
220 };
221
222 template <typename Container>
223 inline typename container_iterator<Container>::type
224 begin(Container& c)
225 {
226 return begin_container<Container>::call(c);
227 }
228
229 inline unused_type const*
230 begin(unused_type)
231 {
232 return &unused;
233 }
234
235 ///////////////////////////////////////////////////////////////////////////
236 template <typename Container, typename Enable = void>
237 struct end_container
238 {
239 static typename container_iterator<Container>::type call(Container& c)
240 {
241 return c.end();
242 }
243 };
244
245 template <typename Container>
246 inline typename container_iterator<Container>::type
247 end(Container& c)
248 {
249 return end_container<Container>::call(c);
250 }
251
252 inline unused_type const*
253 end(unused_type)
254 {
255 return &unused;
256 }
257
258
259 ///////////////////////////////////////////////////////////////////////////
260 template <typename Iterator, typename Enable = void>
261 struct deref_iterator
262 {
263 typedef typename std::iterator_traits<Iterator>::reference type;
264 static type call(Iterator& it)
265 {
266 return *it;
267 }
268 };
269
270 template <typename Iterator>
271 typename deref_iterator<Iterator>::type
272 deref(Iterator& it)
273 {
274 return deref_iterator<Iterator>::call(it);
275 }
276
277 inline unused_type
278 deref(unused_type const*)
279 {
280 return unused;
281 }
282
283 ///////////////////////////////////////////////////////////////////////////
284 template <typename Iterator, typename Enable = void>
285 struct next_iterator
286 {
287 static void call(Iterator& it)
288 {
289 ++it;
290 }
291 };
292
293 template <typename Iterator>
294 void next(Iterator& it)
295 {
296 next_iterator<Iterator>::call(it);
297 }
298
299 inline void next(unused_type const*)
300 {
301 // do nothing
302 }
303
304 ///////////////////////////////////////////////////////////////////////////
305 template <typename Iterator, typename Enable = void>
306 struct compare_iterators
307 {
308 static bool call(Iterator const& it1, Iterator const& it2)
309 {
310 return it1 == it2;
311 }
312 };
313
314 template <typename Iterator>
315 bool compare(Iterator& it1, Iterator& it2)
316 {
317 return compare_iterators<Iterator>::call(it1, it2);
318 }
319
320 inline bool compare(unused_type const*, unused_type const*)
321 {
322 return false;
323 }
324
325 ///////////////////////////////////////////////////////////////////////////
326 template <typename T>
327 struct build_container : mpl::identity<std::vector<T>> {};
328
329 template <typename T>
330 struct build_container<boost::fusion::deque<T> > : build_container<T> {};
331
332 template <>
333 struct build_container<unused_type> : mpl::identity<unused_type> {};
334
335 template <>
336 struct build_container<char> : mpl::identity<std::string> {};
337
338 }}}}
339
340 #endif