1 | 1 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,1134 @@ |
1 |
+/////////////////////////////////////////////////////////////////////////////// |
|
2 |
+// foreach.hpp header file |
|
3 |
+// |
|
4 |
+// Copyright 2004 Eric Niebler. |
|
5 |
+// Distributed under the Boost Software License, Version 1.0. (See |
|
6 |
+// accompanying file LICENSE_1_0.txt or copy at |
|
7 |
+// http://www.boost.org/LICENSE_1_0.txt) |
|
8 |
+// See http://www.boost.org/libs/foreach for documentation |
|
9 |
+// |
|
10 |
+// Credits: |
|
11 |
+// Anson Tsao - for the initial inspiration and several good suggestions. |
|
12 |
+// Thorsten Ottosen - for Boost.Range, and for suggesting a way to detect |
|
13 |
+// const-qualified rvalues at compile time on VC7.1+ |
|
14 |
+// Russell Hind - For help porting to Borland |
|
15 |
+// Alisdair Meredith - For help porting to Borland |
|
16 |
+// Stefan Slapeta - For help porting to Intel |
|
17 |
+// David Jenkins - For help finding a Microsoft Code Analysis bug |
|
18 |
+// mimomorin@... - For a patch to use rvalue refs on supporting compilers |
|
19 |
+ |
|
20 |
+#ifndef BOOST_FOREACH |
|
21 |
+ |
|
22 |
+// MS compatible compilers support #pragma once |
|
23 |
+#if defined(_MSC_VER) |
|
24 |
+# pragma once |
|
25 |
+#endif |
|
26 |
+ |
|
27 |
+#include <cstddef> |
|
28 |
+#include <utility> // for std::pair |
|
29 |
+ |
|
30 |
+#include <boost/config.hpp> |
|
31 |
+#include <boost/detail/workaround.hpp> |
|
32 |
+ |
|
33 |
+// Define a compiler generic null pointer value |
|
34 |
+#if defined(BOOST_NO_NULLPTR) |
|
35 |
+#define BOOST_FOREACH_NULL 0 |
|
36 |
+#else |
|
37 |
+#define BOOST_FOREACH_NULL nullptr |
|
38 |
+#endif |
|
39 |
+ |
|
40 |
+// Some compilers let us detect even const-qualified rvalues at compile-time |
|
41 |
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ |
|
42 |
+ || defined(BOOST_MSVC) && !defined(_PREFAST_) \ |
|
43 |
+ || (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) && \ |
|
44 |
+ !defined(BOOST_CLANG)) \ |
|
45 |
+ || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL) && \ |
|
46 |
+ !defined(BOOST_CLANG)) |
|
47 |
+# define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION |
|
48 |
+#else |
|
49 |
+// Some compilers allow temporaries to be bound to non-const references. |
|
50 |
+// These compilers make it impossible to for BOOST_FOREACH to detect |
|
51 |
+// temporaries and avoid reevaluation of the collection expression. |
|
52 |
+# if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x593) \ |
|
53 |
+ || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \ |
|
54 |
+ || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) \ |
|
55 |
+ || BOOST_WORKAROUND(__DECCXX_VER, <= 60590042) |
|
56 |
+# define BOOST_FOREACH_NO_RVALUE_DETECTION |
|
57 |
+# endif |
|
58 |
+// Some compilers do not correctly implement the lvalue/rvalue conversion |
|
59 |
+// rules of the ternary conditional operator. |
|
60 |
+# if defined(BOOST_FOREACH_NO_RVALUE_DETECTION) \ |
|
61 |
+ || defined(BOOST_NO_SFINAE) \ |
|
62 |
+ || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ |
|
63 |
+ || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(1400)) \ |
|
64 |
+ || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__)) \ |
|
65 |
+ || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) \ |
|
66 |
+ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) \ |
|
67 |
+ || BOOST_WORKAROUND(__SUNPRO_CC, >= 0x5100) \ |
|
68 |
+ || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x590)) |
|
69 |
+# define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION |
|
70 |
+# else |
|
71 |
+# define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
72 |
+# endif |
|
73 |
+#endif |
|
74 |
+ |
|
75 |
+#include <boost/mpl/if.hpp> |
|
76 |
+#include <boost/mpl/assert.hpp> |
|
77 |
+#include <boost/mpl/logical.hpp> |
|
78 |
+#include <boost/mpl/eval_if.hpp> |
|
79 |
+#include <boost/noncopyable.hpp> |
|
80 |
+#include <boost/range/end.hpp> |
|
81 |
+#include <boost/range/begin.hpp> |
|
82 |
+#include <boost/range/rend.hpp> |
|
83 |
+#include <boost/range/rbegin.hpp> |
|
84 |
+#include <boost/range/iterator.hpp> |
|
85 |
+#include <boost/range/reverse_iterator.hpp> |
|
86 |
+#include <boost/type_traits/is_array.hpp> |
|
87 |
+#include <boost/type_traits/is_const.hpp> |
|
88 |
+#include <boost/type_traits/is_abstract.hpp> |
|
89 |
+#include <boost/type_traits/is_base_and_derived.hpp> |
|
90 |
+#include <boost/type_traits/is_rvalue_reference.hpp> |
|
91 |
+#include <boost/iterator/iterator_traits.hpp> |
|
92 |
+#include <boost/utility/addressof.hpp> |
|
93 |
+#include <boost/foreach_fwd.hpp> |
|
94 |
+ |
|
95 |
+#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
96 |
+# include <new> |
|
97 |
+# include <boost/aligned_storage.hpp> |
|
98 |
+# include <boost/utility/enable_if.hpp> |
|
99 |
+# include <boost/type_traits/remove_const.hpp> |
|
100 |
+#endif |
|
101 |
+ |
|
102 |
+namespace boost |
|
103 |
+{ |
|
104 |
+ |
|
105 |
+// forward declarations for iterator_range |
|
106 |
+template<typename T> |
|
107 |
+class iterator_range; |
|
108 |
+ |
|
109 |
+// forward declarations for sub_range |
|
110 |
+template<typename T> |
|
111 |
+class sub_range; |
|
112 |
+ |
|
113 |
+namespace foreach |
|
114 |
+{ |
|
115 |
+ /////////////////////////////////////////////////////////////////////////////// |
|
116 |
+ // in_range |
|
117 |
+ // |
|
118 |
+ template<typename T> |
|
119 |
+ inline std::pair<T, T> in_range(T begin, T end) |
|
120 |
+ { |
|
121 |
+ return std::make_pair(begin, end); |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ /////////////////////////////////////////////////////////////////////////////// |
|
125 |
+ // boost::foreach::is_lightweight_proxy |
|
126 |
+ // Specialize this for user-defined collection types if they are inexpensive to copy. |
|
127 |
+ // This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff. |
|
128 |
+ template<typename T> |
|
129 |
+ struct is_lightweight_proxy |
|
130 |
+ : boost::mpl::false_ |
|
131 |
+ { |
|
132 |
+ }; |
|
133 |
+ |
|
134 |
+ /////////////////////////////////////////////////////////////////////////////// |
|
135 |
+ // boost::foreach::is_noncopyable |
|
136 |
+ // Specialize this for user-defined collection types if they cannot be copied. |
|
137 |
+ // This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff. |
|
138 |
+ template<typename T> |
|
139 |
+ struct is_noncopyable |
|
140 |
+ #if !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) && !defined(BOOST_NO_IS_ABSTRACT) |
|
141 |
+ : boost::mpl::or_< |
|
142 |
+ boost::is_abstract<T> |
|
143 |
+ , boost::is_base_and_derived<boost::noncopyable, T> |
|
144 |
+ > |
|
145 |
+ #elif !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) |
|
146 |
+ : boost::is_base_and_derived<boost::noncopyable, T> |
|
147 |
+ #elif !defined(BOOST_NO_IS_ABSTRACT) |
|
148 |
+ : boost::is_abstract<T> |
|
149 |
+ #else |
|
150 |
+ : boost::mpl::false_ |
|
151 |
+ #endif |
|
152 |
+ { |
|
153 |
+ }; |
|
154 |
+ |
|
155 |
+} // namespace foreach |
|
156 |
+ |
|
157 |
+} // namespace boost |
|
158 |
+ |
|
159 |
+// vc6/7 needs help ordering the following overloads |
|
160 |
+#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
161 |
+# define BOOST_FOREACH_TAG_DEFAULT ... |
|
162 |
+#else |
|
163 |
+# define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag |
|
164 |
+#endif |
|
165 |
+ |
|
166 |
+/////////////////////////////////////////////////////////////////////////////// |
|
167 |
+// boost_foreach_is_lightweight_proxy |
|
168 |
+// Another customization point for the is_lightweight_proxy optimization, |
|
169 |
+// this one works on legacy compilers. Overload boost_foreach_is_lightweight_proxy |
|
170 |
+// at the global namespace for your type. |
|
171 |
+template<typename T> |
|
172 |
+inline boost::foreach::is_lightweight_proxy<T> * |
|
173 |
+boost_foreach_is_lightweight_proxy(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } |
|
174 |
+ |
|
175 |
+template<typename T> |
|
176 |
+inline boost::mpl::true_ * |
|
177 |
+boost_foreach_is_lightweight_proxy(std::pair<T, T> *&, boost::foreach::tag) { return 0; } |
|
178 |
+ |
|
179 |
+template<typename T> |
|
180 |
+inline boost::mpl::true_ * |
|
181 |
+boost_foreach_is_lightweight_proxy(boost::iterator_range<T> *&, boost::foreach::tag) { return 0; } |
|
182 |
+ |
|
183 |
+template<typename T> |
|
184 |
+inline boost::mpl::true_ * |
|
185 |
+boost_foreach_is_lightweight_proxy(boost::sub_range<T> *&, boost::foreach::tag) { return 0; } |
|
186 |
+ |
|
187 |
+template<typename T> |
|
188 |
+inline boost::mpl::true_ * |
|
189 |
+boost_foreach_is_lightweight_proxy(T **&, boost::foreach::tag) { return 0; } |
|
190 |
+ |
|
191 |
+/////////////////////////////////////////////////////////////////////////////// |
|
192 |
+// boost_foreach_is_noncopyable |
|
193 |
+// Another customization point for the is_noncopyable trait, |
|
194 |
+// this one works on legacy compilers. Overload boost_foreach_is_noncopyable |
|
195 |
+// at the global namespace for your type. |
|
196 |
+template<typename T> |
|
197 |
+inline boost::foreach::is_noncopyable<T> * |
|
198 |
+boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } |
|
199 |
+ |
|
200 |
+namespace boost |
|
201 |
+{ |
|
202 |
+ |
|
203 |
+namespace foreach_detail_ |
|
204 |
+{ |
|
205 |
+ |
|
206 |
+/////////////////////////////////////////////////////////////////////////////// |
|
207 |
+// Define some utilities for assessing the properties of expressions |
|
208 |
+// |
|
209 |
+template<typename Bool1, typename Bool2> |
|
210 |
+inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; } |
|
211 |
+ |
|
212 |
+template<typename Bool1, typename Bool2, typename Bool3> |
|
213 |
+inline boost::mpl::and_<Bool1, Bool2, Bool3> *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; } |
|
214 |
+ |
|
215 |
+template<typename Bool1, typename Bool2> |
|
216 |
+inline boost::mpl::or_<Bool1, Bool2> *or_(Bool1 *, Bool2 *) { return 0; } |
|
217 |
+ |
|
218 |
+template<typename Bool1, typename Bool2, typename Bool3> |
|
219 |
+inline boost::mpl::or_<Bool1, Bool2, Bool3> *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; } |
|
220 |
+ |
|
221 |
+template<typename Bool1> |
|
222 |
+inline boost::mpl::not_<Bool1> *not_(Bool1 *) { return 0; } |
|
223 |
+ |
|
224 |
+template<typename T> |
|
225 |
+inline boost::is_array<T> *is_array_(T const &) { return 0; } |
|
226 |
+ |
|
227 |
+template<typename T> |
|
228 |
+inline boost::is_const<T> *is_const_(T &) { return 0; } |
|
229 |
+ |
|
230 |
+#ifndef BOOST_FOREACH_NO_RVALUE_DETECTION |
|
231 |
+template<typename T> |
|
232 |
+inline boost::mpl::true_ *is_const_(T const &) { return 0; } |
|
233 |
+#endif |
|
234 |
+ |
|
235 |
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
|
236 |
+template<typename T> |
|
237 |
+inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; } |
|
238 |
+ |
|
239 |
+template<typename T> |
|
240 |
+inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; } |
|
241 |
+#else |
|
242 |
+template<typename T> |
|
243 |
+inline boost::is_rvalue_reference<T &&> *is_rvalue_(T &&, int) { return 0; } |
|
244 |
+#endif |
|
245 |
+ |
|
246 |
+/////////////////////////////////////////////////////////////////////////////// |
|
247 |
+// auto_any_t/auto_any |
|
248 |
+// General utility for putting an object of any type into automatic storage |
|
249 |
+struct auto_any_base |
|
250 |
+{ |
|
251 |
+ // auto_any_base must evaluate to false in boolean context so that |
|
252 |
+ // they can be declared in if() statements. |
|
253 |
+ operator bool() const |
|
254 |
+ { |
|
255 |
+ return false; |
|
256 |
+ } |
|
257 |
+}; |
|
258 |
+ |
|
259 |
+template<typename T> |
|
260 |
+struct auto_any : auto_any_base |
|
261 |
+{ |
|
262 |
+ explicit auto_any(T const &t) |
|
263 |
+ : item(t) |
|
264 |
+ { |
|
265 |
+ } |
|
266 |
+ |
|
267 |
+ // temporaries of type auto_any will be bound to const auto_any_base |
|
268 |
+ // references, but we still want to be able to mutate the stored |
|
269 |
+ // data, so declare it as mutable. |
|
270 |
+ mutable T item; |
|
271 |
+}; |
|
272 |
+ |
|
273 |
+typedef auto_any_base const &auto_any_t; |
|
274 |
+ |
|
275 |
+template<typename T, typename C> |
|
276 |
+inline BOOST_DEDUCED_TYPENAME boost::mpl::if_<C, T const, T>::type &auto_any_cast(auto_any_t a) |
|
277 |
+{ |
|
278 |
+ return static_cast<auto_any<T> const &>(a).item; |
|
279 |
+} |
|
280 |
+ |
|
281 |
+typedef boost::mpl::true_ const_; |
|
282 |
+ |
|
283 |
+/////////////////////////////////////////////////////////////////////////////// |
|
284 |
+// type2type |
|
285 |
+// |
|
286 |
+template<typename T, typename C = boost::mpl::false_> |
|
287 |
+struct type2type |
|
288 |
+ : boost::mpl::if_<C, T const, T> |
|
289 |
+{ |
|
290 |
+}; |
|
291 |
+ |
|
292 |
+template<typename T> |
|
293 |
+struct wrap_cstr |
|
294 |
+{ |
|
295 |
+ typedef T type; |
|
296 |
+}; |
|
297 |
+ |
|
298 |
+template<> |
|
299 |
+struct wrap_cstr<char *> |
|
300 |
+{ |
|
301 |
+ typedef wrap_cstr<char *> type; |
|
302 |
+ typedef char *iterator; |
|
303 |
+ typedef char *const_iterator; |
|
304 |
+}; |
|
305 |
+ |
|
306 |
+template<> |
|
307 |
+struct wrap_cstr<char const *> |
|
308 |
+{ |
|
309 |
+ typedef wrap_cstr<char const *> type; |
|
310 |
+ typedef char const *iterator; |
|
311 |
+ typedef char const *const_iterator; |
|
312 |
+}; |
|
313 |
+ |
|
314 |
+template<> |
|
315 |
+struct wrap_cstr<wchar_t *> |
|
316 |
+{ |
|
317 |
+ typedef wrap_cstr<wchar_t *> type; |
|
318 |
+ typedef wchar_t *iterator; |
|
319 |
+ typedef wchar_t *const_iterator; |
|
320 |
+}; |
|
321 |
+ |
|
322 |
+template<> |
|
323 |
+struct wrap_cstr<wchar_t const *> |
|
324 |
+{ |
|
325 |
+ typedef wrap_cstr<wchar_t const *> type; |
|
326 |
+ typedef wchar_t const *iterator; |
|
327 |
+ typedef wchar_t const *const_iterator; |
|
328 |
+}; |
|
329 |
+ |
|
330 |
+template<typename T> |
|
331 |
+struct is_char_array |
|
332 |
+ : mpl::and_< |
|
333 |
+ is_array<T> |
|
334 |
+ , mpl::or_< |
|
335 |
+ is_convertible<T, char const *> |
|
336 |
+ , is_convertible<T, wchar_t const *> |
|
337 |
+ > |
|
338 |
+ > |
|
339 |
+{}; |
|
340 |
+ |
|
341 |
+template<typename T, typename C = boost::mpl::false_> |
|
342 |
+struct foreach_iterator |
|
343 |
+{ |
|
344 |
+ // **** READ THIS IF YOUR COMPILE BREAKS HERE **** |
|
345 |
+ // |
|
346 |
+ // There is an ambiguity about how to iterate over arrays of char and wchar_t. |
|
347 |
+ // Should the last array element be treated as a null terminator to be skipped, or |
|
348 |
+ // is it just like any other element in the array? To fix the problem, you must |
|
349 |
+ // say which behavior you want. |
|
350 |
+ // |
|
351 |
+ // To treat the container as a null-terminated string, merely cast it to a |
|
352 |
+ // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... |
|
353 |
+ // |
|
354 |
+ // To treat the container as an array, use boost::as_array() in <boost/range/as_array.hpp>, |
|
355 |
+ // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... |
|
356 |
+ BOOST_MPL_ASSERT_MSG( (!is_char_array<T>::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); |
|
357 |
+ |
|
358 |
+ // If the type is a pointer to a null terminated string (as opposed |
|
359 |
+ // to an array type), there is no ambiguity. |
|
360 |
+ typedef BOOST_DEDUCED_TYPENAME wrap_cstr<T>::type container; |
|
361 |
+ |
|
362 |
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< |
|
363 |
+ C |
|
364 |
+ , range_const_iterator<container> |
|
365 |
+ , range_mutable_iterator<container> |
|
366 |
+ >::type type; |
|
367 |
+}; |
|
368 |
+ |
|
369 |
+ |
|
370 |
+template<typename T, typename C = boost::mpl::false_> |
|
371 |
+struct foreach_reverse_iterator |
|
372 |
+{ |
|
373 |
+ // **** READ THIS IF YOUR COMPILE BREAKS HERE **** |
|
374 |
+ // |
|
375 |
+ // There is an ambiguity about how to iterate over arrays of char and wchar_t. |
|
376 |
+ // Should the last array element be treated as a null terminator to be skipped, or |
|
377 |
+ // is it just like any other element in the array? To fix the problem, you must |
|
378 |
+ // say which behavior you want. |
|
379 |
+ // |
|
380 |
+ // To treat the container as a null-terminated string, merely cast it to a |
|
381 |
+ // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... |
|
382 |
+ // |
|
383 |
+ // To treat the container as an array, use boost::as_array() in <boost/range/as_array.hpp>, |
|
384 |
+ // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... |
|
385 |
+ BOOST_MPL_ASSERT_MSG( (!is_char_array<T>::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); |
|
386 |
+ |
|
387 |
+ // If the type is a pointer to a null terminated string (as opposed |
|
388 |
+ // to an array type), there is no ambiguity. |
|
389 |
+ typedef BOOST_DEDUCED_TYPENAME wrap_cstr<T>::type container; |
|
390 |
+ |
|
391 |
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< |
|
392 |
+ C |
|
393 |
+ , range_reverse_iterator<container const> |
|
394 |
+ , range_reverse_iterator<container> |
|
395 |
+ >::type type; |
|
396 |
+}; |
|
397 |
+ |
|
398 |
+template<typename T, typename C = boost::mpl::false_> |
|
399 |
+struct foreach_reference |
|
400 |
+ : iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
|
401 |
+{ |
|
402 |
+}; |
|
403 |
+ |
|
404 |
+/////////////////////////////////////////////////////////////////////////////// |
|
405 |
+// encode_type |
|
406 |
+// |
|
407 |
+template<typename T> |
|
408 |
+inline type2type<T> *encode_type(T &, boost::false_type*) { return 0; } |
|
409 |
+ |
|
410 |
+template<typename T> |
|
411 |
+inline type2type<T, const_> *encode_type(T const &, boost::true_type*) { return 0; } |
|
412 |
+ |
|
413 |
+template<typename T> |
|
414 |
+inline type2type<T> *encode_type(T &, boost::mpl::false_*) { return 0; } |
|
415 |
+ |
|
416 |
+template<typename T> |
|
417 |
+inline type2type<T, const_> *encode_type(T const &, boost::mpl::true_*) { return 0; } |
|
418 |
+ |
|
419 |
+/////////////////////////////////////////////////////////////////////////////// |
|
420 |
+// set_false |
|
421 |
+// |
|
422 |
+inline bool set_false(bool &b) |
|
423 |
+{ |
|
424 |
+ b = false; |
|
425 |
+ return false; |
|
426 |
+} |
|
427 |
+ |
|
428 |
+/////////////////////////////////////////////////////////////////////////////// |
|
429 |
+// to_ptr |
|
430 |
+// |
|
431 |
+template<typename T> |
|
432 |
+inline T *&to_ptr(T const &) |
|
433 |
+{ |
|
434 |
+ static T *t = 0; |
|
435 |
+ return t; |
|
436 |
+} |
|
437 |
+ |
|
438 |
+// Borland needs a little extra help with arrays |
|
439 |
+#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
|
440 |
+template<typename T,std::size_t N> |
|
441 |
+inline T (*&to_ptr(T (&)[N]))[N] |
|
442 |
+{ |
|
443 |
+ static T (*t)[N] = 0; |
|
444 |
+ return t; |
|
445 |
+} |
|
446 |
+ |
|
447 |
+/////////////////////////////////////////////////////////////////////////////// |
|
448 |
+// derefof |
|
449 |
+// |
|
450 |
+template<typename T> |
|
451 |
+inline T &derefof(T *t) |
|
452 |
+{ |
|
453 |
+ // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N], |
|
454 |
+ // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue. |
|
455 |
+ return reinterpret_cast<T &>( |
|
456 |
+ *const_cast<char *>( |
|
457 |
+ reinterpret_cast<char const volatile *>(t) |
|
458 |
+ ) |
|
459 |
+ ); |
|
460 |
+} |
|
461 |
+ |
|
462 |
+# define BOOST_FOREACH_DEREFOF(T) boost::foreach_detail_::derefof(*T) |
|
463 |
+#else |
|
464 |
+# define BOOST_FOREACH_DEREFOF(T) (*T) |
|
465 |
+#endif |
|
466 |
+ |
|
467 |
+#if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ |
|
468 |
+ && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
|
469 |
+/////////////////////////////////////////////////////////////////////////////// |
|
470 |
+// Rvalue references makes it drop-dead simple to detect at compile time |
|
471 |
+// whether an expression is an rvalue. |
|
472 |
+/////////////////////////////////////////////////////////////////////////////// |
|
473 |
+ |
|
474 |
+# define BOOST_FOREACH_IS_RVALUE(COL) \ |
|
475 |
+ boost::foreach_detail_::is_rvalue_((COL), 0) |
|
476 |
+ |
|
477 |
+#elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ |
|
478 |
+ && defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
|
479 |
+/////////////////////////////////////////////////////////////////////////////// |
|
480 |
+// Detect at compile-time whether an expression yields an rvalue or |
|
481 |
+// an lvalue. This is rather non-standard, but some popular compilers |
|
482 |
+// accept it. |
|
483 |
+/////////////////////////////////////////////////////////////////////////////// |
|
484 |
+ |
|
485 |
+/////////////////////////////////////////////////////////////////////////////// |
|
486 |
+// rvalue_probe |
|
487 |
+// |
|
488 |
+template<typename T> |
|
489 |
+struct rvalue_probe |
|
490 |
+{ |
|
491 |
+ struct private_type_ {}; |
|
492 |
+ // can't ever return an array by value |
|
493 |
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< |
|
494 |
+ boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T |
|
495 |
+ >::type value_type; |
|
496 |
+ operator value_type() { return *reinterpret_cast<value_type *>(this); } // never called |
|
497 |
+ operator T &() const { return *reinterpret_cast<T *>(const_cast<rvalue_probe *>(this)); } // never called |
|
498 |
+}; |
|
499 |
+ |
|
500 |
+template<typename T> |
|
501 |
+rvalue_probe<T> const make_probe(T const &) |
|
502 |
+{ |
|
503 |
+ return rvalue_probe<T>(); |
|
504 |
+} |
|
505 |
+ |
|
506 |
+# define BOOST_FOREACH_IS_RVALUE(COL) \ |
|
507 |
+ boost::foreach_detail_::and_( \ |
|
508 |
+ boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL)) \ |
|
509 |
+ , (true ? 0 : boost::foreach_detail_::is_rvalue_( \ |
|
510 |
+ (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0))) |
|
511 |
+ |
|
512 |
+#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) |
|
513 |
+/////////////////////////////////////////////////////////////////////////////// |
|
514 |
+// Detect at run-time whether an expression yields an rvalue |
|
515 |
+// or an lvalue. This is 100% standard C++, but not all compilers |
|
516 |
+// accept it. Also, it causes FOREACH to break when used with non- |
|
517 |
+// copyable collection types. |
|
518 |
+/////////////////////////////////////////////////////////////////////////////// |
|
519 |
+ |
|
520 |
+/////////////////////////////////////////////////////////////////////////////// |
|
521 |
+// rvalue_probe |
|
522 |
+// |
|
523 |
+template<typename T> |
|
524 |
+struct rvalue_probe |
|
525 |
+{ |
|
526 |
+ rvalue_probe(T &t, bool &b) |
|
527 |
+ : value(t) |
|
528 |
+ , is_rvalue(b) |
|
529 |
+ { |
|
530 |
+ } |
|
531 |
+ |
|
532 |
+ struct private_type_ {}; |
|
533 |
+ // can't ever return an array or an abstract type by value |
|
534 |
+ #ifdef BOOST_NO_IS_ABSTRACT |
|
535 |
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< |
|
536 |
+ boost::is_array<T>, private_type_, T |
|
537 |
+ >::type value_type; |
|
538 |
+ #else |
|
539 |
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< |
|
540 |
+ boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T |
|
541 |
+ >::type value_type; |
|
542 |
+ #endif |
|
543 |
+ |
|
544 |
+ operator value_type() |
|
545 |
+ { |
|
546 |
+ this->is_rvalue = true; |
|
547 |
+ return this->value; |
|
548 |
+ } |
|
549 |
+ |
|
550 |
+ operator T &() const |
|
551 |
+ { |
|
552 |
+ return this->value; |
|
553 |
+ } |
|
554 |
+ |
|
555 |
+private: |
|
556 |
+ T &value; |
|
557 |
+ bool &is_rvalue; |
|
558 |
+}; |
|
559 |
+ |
|
560 |
+template<typename T> |
|
561 |
+rvalue_probe<T> make_probe(T &t, bool &b) { return rvalue_probe<T>(t, b); } |
|
562 |
+ |
|
563 |
+template<typename T> |
|
564 |
+rvalue_probe<T const> make_probe(T const &t, bool &b) { return rvalue_probe<T const>(t, b); } |
|
565 |
+ |
|
566 |
+/////////////////////////////////////////////////////////////////////////////// |
|
567 |
+// simple_variant |
|
568 |
+// holds either a T or a T const* |
|
569 |
+template<typename T> |
|
570 |
+struct simple_variant |
|
571 |
+{ |
|
572 |
+ simple_variant(T const *t) |
|
573 |
+ : is_rvalue(false) |
|
574 |
+ { |
|
575 |
+ *static_cast<T const **>(this->data.address()) = t; |
|
576 |
+ } |
|
577 |
+ |
|
578 |
+ simple_variant(T const &t) |
|
579 |
+ : is_rvalue(true) |
|
580 |
+ { |
|
581 |
+ ::new(this->data.address()) T(t); |
|
582 |
+ } |
|
583 |
+ |
|
584 |
+ simple_variant(simple_variant const &that) |
|
585 |
+ : is_rvalue(that.is_rvalue) |
|
586 |
+ { |
|
587 |
+ if(this->is_rvalue) |
|
588 |
+ ::new(this->data.address()) T(*that.get()); |
|
589 |
+ else |
|
590 |
+ *static_cast<T const **>(this->data.address()) = that.get(); |
|
591 |
+ } |
|
592 |
+ |
|
593 |
+ ~simple_variant() |
|
594 |
+ { |
|
595 |
+ if(this->is_rvalue) |
|
596 |
+ this->get()->~T(); |
|
597 |
+ } |
|
598 |
+ |
|
599 |
+ T const *get() const |
|
600 |
+ { |
|
601 |
+ if(this->is_rvalue) |
|
602 |
+ return static_cast<T const *>(this->data.address()); |
|
603 |
+ else |
|
604 |
+ return *static_cast<T const * const *>(this->data.address()); |
|
605 |
+ } |
|
606 |
+ |
|
607 |
+private: |
|
608 |
+ enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) }; |
|
609 |
+ simple_variant &operator =(simple_variant const &); |
|
610 |
+ bool const is_rvalue; |
|
611 |
+ aligned_storage<size> data; |
|
612 |
+}; |
|
613 |
+ |
|
614 |
+// If the collection is an array or is noncopyable, it must be an lvalue. |
|
615 |
+// If the collection is a lightweight proxy, treat it as an rvalue |
|
616 |
+// BUGBUG what about a noncopyable proxy? |
|
617 |
+template<typename LValue, typename IsProxy> |
|
618 |
+inline BOOST_DEDUCED_TYPENAME boost::enable_if<boost::mpl::or_<LValue, IsProxy>, IsProxy>::type * |
|
619 |
+should_copy_impl(LValue *, IsProxy *, bool *) |
|
620 |
+{ |
|
621 |
+ return 0; |
|
622 |
+} |
|
623 |
+ |
|
624 |
+// Otherwise, we must determine at runtime whether it's an lvalue or rvalue |
|
625 |
+inline bool * |
|
626 |
+should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue) |
|
627 |
+{ |
|
628 |
+ return is_rvalue; |
|
629 |
+} |
|
630 |
+ |
|
631 |
+#endif |
|
632 |
+ |
|
633 |
+/////////////////////////////////////////////////////////////////////////////// |
|
634 |
+// contain |
|
635 |
+// |
|
636 |
+template<typename T> |
|
637 |
+inline auto_any<T> contain(T const &t, boost::mpl::true_ *) // rvalue |
|
638 |
+{ |
|
639 |
+ return auto_any<T>(t); |
|
640 |
+} |
|
641 |
+ |
|
642 |
+template<typename T> |
|
643 |
+inline auto_any<T *> contain(T &t, boost::mpl::false_ *) // lvalue |
|
644 |
+{ |
|
645 |
+ // Cannot seem to get sunpro to handle addressof() with array types. |
|
646 |
+ #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570)) |
|
647 |
+ return auto_any<T *>(&t); |
|
648 |
+ #else |
|
649 |
+ return auto_any<T *>(boost::addressof(t)); |
|
650 |
+ #endif |
|
651 |
+} |
|
652 |
+ |
|
653 |
+#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
654 |
+template<typename T> |
|
655 |
+inline auto_any<simple_variant<T> > |
|
656 |
+contain(T const &t, bool *rvalue) |
|
657 |
+{ |
|
658 |
+ return auto_any<simple_variant<T> >(*rvalue ? simple_variant<T>(t) : simple_variant<T>(&t)); |
|
659 |
+} |
|
660 |
+#endif |
|
661 |
+ |
|
662 |
+///////////////////////////////////////////////////////////////////////////// |
|
663 |
+// begin |
|
664 |
+// |
|
665 |
+template<typename T, typename C> |
|
666 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
|
667 |
+begin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
|
668 |
+{ |
|
669 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
|
670 |
+ boost::begin(auto_any_cast<T, C>(col))); |
|
671 |
+} |
|
672 |
+ |
|
673 |
+template<typename T, typename C> |
|
674 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
|
675 |
+begin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
|
676 |
+{ |
|
677 |
+ typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
|
678 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator; |
|
679 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
|
680 |
+ iterator(boost::begin(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
|
681 |
+} |
|
682 |
+ |
|
683 |
+#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
684 |
+template<typename T> |
|
685 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type> |
|
686 |
+begin(auto_any_t col, type2type<T, const_> *, bool *) |
|
687 |
+{ |
|
688 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>( |
|
689 |
+ boost::begin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
|
690 |
+} |
|
691 |
+#endif |
|
692 |
+ |
|
693 |
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
694 |
+template<typename T, typename C> |
|
695 |
+inline auto_any<T *> |
|
696 |
+begin(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
|
697 |
+{ |
|
698 |
+ return auto_any<T *>(auto_any_cast<T *, boost::mpl::false_>(col)); |
|
699 |
+} |
|
700 |
+#endif |
|
701 |
+ |
|
702 |
+/////////////////////////////////////////////////////////////////////////////// |
|
703 |
+// end |
|
704 |
+// |
|
705 |
+template<typename T, typename C> |
|
706 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
|
707 |
+end(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
|
708 |
+{ |
|
709 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
|
710 |
+ boost::end(auto_any_cast<T, C>(col))); |
|
711 |
+} |
|
712 |
+ |
|
713 |
+template<typename T, typename C> |
|
714 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
|
715 |
+end(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
|
716 |
+{ |
|
717 |
+ typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
|
718 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator; |
|
719 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
|
720 |
+ iterator(boost::end(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
|
721 |
+} |
|
722 |
+ |
|
723 |
+#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
724 |
+template<typename T> |
|
725 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type> |
|
726 |
+end(auto_any_t col, type2type<T, const_> *, bool *) |
|
727 |
+{ |
|
728 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>( |
|
729 |
+ boost::end(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
|
730 |
+} |
|
731 |
+#endif |
|
732 |
+ |
|
733 |
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
734 |
+template<typename T, typename C> |
|
735 |
+inline auto_any<int> |
|
736 |
+end(auto_any_t, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
|
737 |
+{ |
|
738 |
+ return auto_any<int>(0); // not used |
|
739 |
+} |
|
740 |
+#endif |
|
741 |
+ |
|
742 |
+/////////////////////////////////////////////////////////////////////////////// |
|
743 |
+// done |
|
744 |
+// |
|
745 |
+template<typename T, typename C> |
|
746 |
+inline bool done(auto_any_t cur, auto_any_t end, type2type<T, C> *) |
|
747 |
+{ |
|
748 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t; |
|
749 |
+ return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end); |
|
750 |
+} |
|
751 |
+ |
|
752 |
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
753 |
+template<typename T, typename C> |
|
754 |
+inline bool done(auto_any_t cur, auto_any_t, type2type<T *, C> *) // null-terminated C-style strings |
|
755 |
+{ |
|
756 |
+ return ! *auto_any_cast<T *, boost::mpl::false_>(cur); |
|
757 |
+} |
|
758 |
+#endif |
|
759 |
+ |
|
760 |
+/////////////////////////////////////////////////////////////////////////////// |
|
761 |
+// next |
|
762 |
+// |
|
763 |
+template<typename T, typename C> |
|
764 |
+inline void next(auto_any_t cur, type2type<T, C> *) |
|
765 |
+{ |
|
766 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t; |
|
767 |
+ ++auto_any_cast<iter_t, boost::mpl::false_>(cur); |
|
768 |
+} |
|
769 |
+ |
|
770 |
+/////////////////////////////////////////////////////////////////////////////// |
|
771 |
+// deref |
|
772 |
+// |
|
773 |
+template<typename T, typename C> |
|
774 |
+inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type |
|
775 |
+deref(auto_any_t cur, type2type<T, C> *) |
|
776 |
+{ |
|
777 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t; |
|
778 |
+ return *auto_any_cast<iter_t, boost::mpl::false_>(cur); |
|
779 |
+} |
|
780 |
+ |
|
781 |
+///////////////////////////////////////////////////////////////////////////// |
|
782 |
+// rbegin |
|
783 |
+// |
|
784 |
+template<typename T, typename C> |
|
785 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
|
786 |
+rbegin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
|
787 |
+{ |
|
788 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
|
789 |
+ boost::rbegin(auto_any_cast<T, C>(col))); |
|
790 |
+} |
|
791 |
+ |
|
792 |
+template<typename T, typename C> |
|
793 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
|
794 |
+rbegin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
|
795 |
+{ |
|
796 |
+ typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
|
797 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iterator; |
|
798 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
|
799 |
+ iterator(boost::rbegin(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
|
800 |
+} |
|
801 |
+ |
|
802 |
+#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
803 |
+template<typename T> |
|
804 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type> |
|
805 |
+rbegin(auto_any_t col, type2type<T, const_> *, bool *) |
|
806 |
+{ |
|
807 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type>( |
|
808 |
+ boost::rbegin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
|
809 |
+} |
|
810 |
+#endif |
|
811 |
+ |
|
812 |
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
813 |
+template<typename T, typename C> |
|
814 |
+inline auto_any<reverse_iterator<T *> > |
|
815 |
+rbegin(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
|
816 |
+{ |
|
817 |
+ T *p = auto_any_cast<T *, boost::mpl::false_>(col); |
|
818 |
+ while(0 != *p) |
|
819 |
+ ++p; |
|
820 |
+ return auto_any<reverse_iterator<T *> >(reverse_iterator<T *>(p)); |
|
821 |
+} |
|
822 |
+#endif |
|
823 |
+ |
|
824 |
+/////////////////////////////////////////////////////////////////////////////// |
|
825 |
+// rend |
|
826 |
+// |
|
827 |
+template<typename T, typename C> |
|
828 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
|
829 |
+rend(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
|
830 |
+{ |
|
831 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
|
832 |
+ boost::rend(auto_any_cast<T, C>(col))); |
|
833 |
+} |
|
834 |
+ |
|
835 |
+template<typename T, typename C> |
|
836 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
|
837 |
+rend(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
|
838 |
+{ |
|
839 |
+ typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
|
840 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iterator; |
|
841 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
|
842 |
+ iterator(boost::rend(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
|
843 |
+} |
|
844 |
+ |
|
845 |
+#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
|
846 |
+template<typename T> |
|
847 |
+inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type> |
|
848 |
+rend(auto_any_t col, type2type<T, const_> *, bool *) |
|
849 |
+{ |
|
850 |
+ return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type>( |
|
851 |
+ boost::rend(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
|
852 |
+} |
|
853 |
+#endif |
|
854 |
+ |
|
855 |
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
856 |
+template<typename T, typename C> |
|
857 |
+inline auto_any<reverse_iterator<T *> > |
|
858 |
+rend(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
|
859 |
+{ |
|
860 |
+ return auto_any<reverse_iterator<T *> >( |
|
861 |
+ reverse_iterator<T *>(auto_any_cast<T *, boost::mpl::false_>(col))); |
|
862 |
+} |
|
863 |
+#endif |
|
864 |
+ |
|
865 |
+/////////////////////////////////////////////////////////////////////////////// |
|
866 |
+// rdone |
|
867 |
+// |
|
868 |
+template<typename T, typename C> |
|
869 |
+inline bool rdone(auto_any_t cur, auto_any_t end, type2type<T, C> *) |
|
870 |
+{ |
|
871 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t; |
|
872 |
+ return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end); |
|
873 |
+} |
|
874 |
+ |
|
875 |
+/////////////////////////////////////////////////////////////////////////////// |
|
876 |
+// rnext |
|
877 |
+// |
|
878 |
+template<typename T, typename C> |
|
879 |
+inline void rnext(auto_any_t cur, type2type<T, C> *) |
|
880 |
+{ |
|
881 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t; |
|
882 |
+ ++auto_any_cast<iter_t, boost::mpl::false_>(cur); |
|
883 |
+} |
|
884 |
+ |
|
885 |
+/////////////////////////////////////////////////////////////////////////////// |
|
886 |
+// rderef |
|
887 |
+// |
|
888 |
+template<typename T, typename C> |
|
889 |
+inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type |
|
890 |
+rderef(auto_any_t cur, type2type<T, C> *) |
|
891 |
+{ |
|
892 |
+ typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t; |
|
893 |
+ return *auto_any_cast<iter_t, boost::mpl::false_>(cur); |
|
894 |
+} |
|
895 |
+ |
|