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 | // Some compilers let us detect even const-qualified rvalues at compile-time |
34 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ |
35 | || defined(BOOST_MSVC) && !defined(_PREFAST_) \ |
36 | || (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) && \ |
37 | !defined(BOOST_CLANG)) \ |
38 | || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL) && \ |
39 | !defined(BOOST_CLANG)) |
40 | # define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION |
41 | #else |
42 | // Some compilers allow temporaries to be bound to non-const references. |
43 | // These compilers make it impossible to for BOOST_FOREACH to detect |
44 | // temporaries and avoid reevaluation of the collection expression. |
45 | # if BOOST_WORKAROUND(__BORLANDC__, < 0x593) \ |
46 | || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \ |
47 | || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) \ |
48 | || BOOST_WORKAROUND(__DECCXX_VER, <= 60590042) |
49 | # define BOOST_FOREACH_NO_RVALUE_DETECTION |
50 | # endif |
51 | // Some compilers do not correctly implement the lvalue/rvalue conversion |
52 | // rules of the ternary conditional operator. |
53 | # if defined(BOOST_FOREACH_NO_RVALUE_DETECTION) \ |
54 | || defined(BOOST_NO_SFINAE) \ |
55 | || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ |
56 | || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(1400)) \ |
57 | || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__)) \ |
58 | || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) \ |
59 | || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) \ |
60 | || BOOST_WORKAROUND(__SUNPRO_CC, >= 0x5100) \ |
61 | || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x590)) |
62 | # define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION |
63 | # else |
64 | # define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
65 | # endif |
66 | #endif |
67 | |
68 | #include <boost/mpl/if.hpp> |
69 | #include <boost/mpl/assert.hpp> |
70 | #include <boost/mpl/logical.hpp> |
71 | #include <boost/mpl/eval_if.hpp> |
72 | #include <boost/noncopyable.hpp> |
73 | #include <boost/range/end.hpp> |
74 | #include <boost/range/begin.hpp> |
75 | #include <boost/range/rend.hpp> |
76 | #include <boost/range/rbegin.hpp> |
77 | #include <boost/range/iterator.hpp> |
78 | #include <boost/range/reverse_iterator.hpp> |
79 | #include <boost/type_traits/is_array.hpp> |
80 | #include <boost/type_traits/is_const.hpp> |
81 | #include <boost/type_traits/is_abstract.hpp> |
82 | #include <boost/type_traits/is_base_and_derived.hpp> |
83 | #include <boost/type_traits/is_rvalue_reference.hpp> |
84 | #include <boost/iterator/iterator_traits.hpp> |
85 | #include <boost/utility/addressof.hpp> |
86 | #include <boost/foreach_fwd.hpp> |
87 | |
88 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
89 | # include <new> |
90 | # include <boost/aligned_storage.hpp> |
91 | # include <boost/utility/enable_if.hpp> |
92 | # include <boost/type_traits/remove_const.hpp> |
93 | #endif |
94 | |
95 | namespace boost |
96 | { |
97 | |
98 | // forward declarations for iterator_range |
99 | template<typename T> |
100 | class iterator_range; |
101 | |
102 | // forward declarations for sub_range |
103 | template<typename T> |
104 | class sub_range; |
105 | |
106 | namespace foreach |
107 | { |
108 | /////////////////////////////////////////////////////////////////////////////// |
109 | // in_range |
110 | // |
111 | template<typename T> |
112 | inline std::pair<T, T> in_range(T begin, T end) |
113 | { |
114 | return std::make_pair(begin, end); |
115 | } |
116 | |
117 | /////////////////////////////////////////////////////////////////////////////// |
118 | // boost::foreach::is_lightweight_proxy |
119 | // Specialize this for user-defined collection types if they are inexpensive to copy. |
120 | // This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff. |
121 | template<typename T> |
122 | struct is_lightweight_proxy |
123 | : boost::mpl::false_ |
124 | { |
125 | }; |
126 | |
127 | /////////////////////////////////////////////////////////////////////////////// |
128 | // boost::foreach::is_noncopyable |
129 | // Specialize this for user-defined collection types if they cannot be copied. |
130 | // This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff. |
131 | template<typename T> |
132 | struct is_noncopyable |
133 | #if !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) && !defined(BOOST_NO_IS_ABSTRACT) |
134 | : boost::mpl::or_< |
135 | boost::is_abstract<T> |
136 | , boost::is_base_and_derived<boost::noncopyable, T> |
137 | > |
138 | #elif !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) |
139 | : boost::is_base_and_derived<boost::noncopyable, T> |
140 | #elif !defined(BOOST_NO_IS_ABSTRACT) |
141 | : boost::is_abstract<T> |
142 | #else |
143 | : boost::mpl::false_ |
144 | #endif |
145 | { |
146 | }; |
147 | |
148 | } // namespace foreach |
149 | |
150 | } // namespace boost |
151 | |
152 | // vc6/7 needs help ordering the following overloads |
153 | #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
154 | # define BOOST_FOREACH_TAG_DEFAULT ... |
155 | #else |
156 | # define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag |
157 | #endif |
158 | |
159 | /////////////////////////////////////////////////////////////////////////////// |
160 | // boost_foreach_is_lightweight_proxy |
161 | // Another customization point for the is_lightweight_proxy optimization, |
162 | // this one works on legacy compilers. Overload boost_foreach_is_lightweight_proxy |
163 | // at the global namespace for your type. |
164 | template<typename T> |
165 | inline boost::foreach::is_lightweight_proxy<T> * |
166 | boost_foreach_is_lightweight_proxy(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } |
167 | |
168 | template<typename T> |
169 | inline boost::mpl::true_ * |
170 | boost_foreach_is_lightweight_proxy(std::pair<T, T> *&, boost::foreach::tag) { return 0; } |
171 | |
172 | template<typename T> |
173 | inline boost::mpl::true_ * |
174 | boost_foreach_is_lightweight_proxy(boost::iterator_range<T> *&, boost::foreach::tag) { return 0; } |
175 | |
176 | template<typename T> |
177 | inline boost::mpl::true_ * |
178 | boost_foreach_is_lightweight_proxy(boost::sub_range<T> *&, boost::foreach::tag) { return 0; } |
179 | |
180 | template<typename T> |
181 | inline boost::mpl::true_ * |
182 | boost_foreach_is_lightweight_proxy(T **&, boost::foreach::tag) { return 0; } |
183 | |
184 | /////////////////////////////////////////////////////////////////////////////// |
185 | // boost_foreach_is_noncopyable |
186 | // Another customization point for the is_noncopyable trait, |
187 | // this one works on legacy compilers. Overload boost_foreach_is_noncopyable |
188 | // at the global namespace for your type. |
189 | template<typename T> |
190 | inline boost::foreach::is_noncopyable<T> * |
191 | boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } |
192 | |
193 | namespace boost |
194 | { |
195 | |
196 | namespace foreach_detail_ |
197 | { |
198 | |
199 | /////////////////////////////////////////////////////////////////////////////// |
200 | // Define some utilities for assessing the properties of expressions |
201 | // |
202 | template<typename Bool1, typename Bool2> |
203 | inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; } |
204 | |
205 | template<typename Bool1, typename Bool2, typename Bool3> |
206 | inline boost::mpl::and_<Bool1, Bool2, Bool3> *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; } |
207 | |
208 | template<typename Bool1, typename Bool2> |
209 | inline boost::mpl::or_<Bool1, Bool2> *or_(Bool1 *, Bool2 *) { return 0; } |
210 | |
211 | template<typename Bool1, typename Bool2, typename Bool3> |
212 | inline boost::mpl::or_<Bool1, Bool2, Bool3> *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; } |
213 | |
214 | template<typename Bool1> |
215 | inline boost::mpl::not_<Bool1> *not_(Bool1 *) { return 0; } |
216 | |
217 | template<typename T> |
218 | inline boost::is_array<T> *is_array_(T const &) { return 0; } |
219 | |
220 | template<typename T> |
221 | inline boost::is_const<T> *is_const_(T &) { return 0; } |
222 | |
223 | #ifndef BOOST_FOREACH_NO_RVALUE_DETECTION |
224 | template<typename T> |
225 | inline boost::mpl::true_ *is_const_(T const &) { return 0; } |
226 | #endif |
227 | |
228 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
229 | template<typename T> |
230 | inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; } |
231 | |
232 | template<typename T> |
233 | inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; } |
234 | #else |
235 | template<typename T> |
236 | inline boost::is_rvalue_reference<T &&> *is_rvalue_(T &&, int) { return 0; } |
237 | #endif |
238 | |
239 | /////////////////////////////////////////////////////////////////////////////// |
240 | // auto_any_t/auto_any |
241 | // General utility for putting an object of any type into automatic storage |
242 | struct auto_any_base |
243 | { |
244 | // auto_any_base must evaluate to false in boolean context so that |
245 | // they can be declared in if() statements. |
246 | operator bool() const |
247 | { |
248 | return false; |
249 | } |
250 | }; |
251 | |
252 | template<typename T> |
253 | struct auto_any : auto_any_base |
254 | { |
255 | explicit auto_any(T const &t) |
256 | : item(t) |
257 | { |
258 | } |
259 | |
260 | // temporaries of type auto_any will be bound to const auto_any_base |
261 | // references, but we still want to be able to mutate the stored |
262 | // data, so declare it as mutable. |
263 | mutable T item; |
264 | }; |
265 | |
266 | typedef auto_any_base const &auto_any_t; |
267 | |
268 | template<typename T, typename C> |
269 | inline BOOST_DEDUCED_TYPENAME boost::mpl::if_<C, T const, T>::type &auto_any_cast(auto_any_t a) |
270 | { |
271 | return static_cast<auto_any<T> const &>(a).item; |
272 | } |
273 | |
274 | typedef boost::mpl::true_ const_; |
275 | |
276 | /////////////////////////////////////////////////////////////////////////////// |
277 | // type2type |
278 | // |
279 | template<typename T, typename C = boost::mpl::false_> |
280 | struct type2type |
281 | : boost::mpl::if_<C, T const, T> |
282 | { |
283 | }; |
284 | |
285 | template<typename T> |
286 | struct wrap_cstr |
287 | { |
288 | typedef T type; |
289 | }; |
290 | |
291 | template<> |
292 | struct wrap_cstr<char *> |
293 | { |
294 | typedef wrap_cstr<char *> type; |
295 | typedef char *iterator; |
296 | typedef char *const_iterator; |
297 | }; |
298 | |
299 | template<> |
300 | struct wrap_cstr<char const *> |
301 | { |
302 | typedef wrap_cstr<char const *> type; |
303 | typedef char const *iterator; |
304 | typedef char const *const_iterator; |
305 | }; |
306 | |
307 | template<> |
308 | struct wrap_cstr<wchar_t *> |
309 | { |
310 | typedef wrap_cstr<wchar_t *> type; |
311 | typedef wchar_t *iterator; |
312 | typedef wchar_t *const_iterator; |
313 | }; |
314 | |
315 | template<> |
316 | struct wrap_cstr<wchar_t const *> |
317 | { |
318 | typedef wrap_cstr<wchar_t const *> type; |
319 | typedef wchar_t const *iterator; |
320 | typedef wchar_t const *const_iterator; |
321 | }; |
322 | |
323 | template<typename T> |
324 | struct is_char_array |
325 | : mpl::and_< |
326 | is_array<T> |
327 | , mpl::or_< |
328 | is_convertible<T, char const *> |
329 | , is_convertible<T, wchar_t const *> |
330 | > |
331 | > |
332 | {}; |
333 | |
334 | template<typename T, typename C = boost::mpl::false_> |
335 | struct foreach_iterator |
336 | { |
337 | // **** READ THIS IF YOUR COMPILE BREAKS HERE **** |
338 | // |
339 | // There is an ambiguity about how to iterate over arrays of char and wchar_t. |
340 | // Should the last array element be treated as a null terminator to be skipped, or |
341 | // is it just like any other element in the array? To fix the problem, you must |
342 | // say which behavior you want. |
343 | // |
344 | // To treat the container as a null-terminated string, merely cast it to a |
345 | // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... |
346 | // |
347 | // To treat the container as an array, use boost::as_array() in <boost/range/as_array.hpp>, |
348 | // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... |
349 | BOOST_MPL_ASSERT_MSG( (!is_char_array<T>::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); |
350 | |
351 | // If the type is a pointer to a null terminated string (as opposed |
352 | // to an array type), there is no ambiguity. |
353 | typedef BOOST_DEDUCED_TYPENAME wrap_cstr<T>::type container; |
354 | |
355 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< |
356 | C |
357 | , range_const_iterator<container> |
358 | , range_mutable_iterator<container> |
359 | >::type type; |
360 | }; |
361 | |
362 | |
363 | template<typename T, typename C = boost::mpl::false_> |
364 | struct foreach_reverse_iterator |
365 | { |
366 | // **** READ THIS IF YOUR COMPILE BREAKS HERE **** |
367 | // |
368 | // There is an ambiguity about how to iterate over arrays of char and wchar_t. |
369 | // Should the last array element be treated as a null terminator to be skipped, or |
370 | // is it just like any other element in the array? To fix the problem, you must |
371 | // say which behavior you want. |
372 | // |
373 | // To treat the container as a null-terminated string, merely cast it to a |
374 | // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... |
375 | // |
376 | // To treat the container as an array, use boost::as_array() in <boost/range/as_array.hpp>, |
377 | // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... |
378 | BOOST_MPL_ASSERT_MSG( (!is_char_array<T>::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); |
379 | |
380 | // If the type is a pointer to a null terminated string (as opposed |
381 | // to an array type), there is no ambiguity. |
382 | typedef BOOST_DEDUCED_TYPENAME wrap_cstr<T>::type container; |
383 | |
384 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< |
385 | C |
386 | , range_reverse_iterator<container const> |
387 | , range_reverse_iterator<container> |
388 | >::type type; |
389 | }; |
390 | |
391 | template<typename T, typename C = boost::mpl::false_> |
392 | struct foreach_reference |
393 | : iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
394 | { |
395 | }; |
396 | |
397 | /////////////////////////////////////////////////////////////////////////////// |
398 | // encode_type |
399 | // |
400 | template<typename T> |
401 | inline type2type<T> *encode_type(T &, boost::false_type*) { return 0; } |
402 | |
403 | template<typename T> |
404 | inline type2type<T, const_> *encode_type(T const &, boost::true_type*) { return 0; } |
405 | |
406 | template<typename T> |
407 | inline type2type<T> *encode_type(T &, boost::mpl::false_*) { return 0; } |
408 | |
409 | template<typename T> |
410 | inline type2type<T, const_> *encode_type(T const &, boost::mpl::true_*) { return 0; } |
411 | |
412 | /////////////////////////////////////////////////////////////////////////////// |
413 | // set_false |
414 | // |
415 | inline bool set_false(bool &b) |
416 | { |
417 | b = false; |
418 | return false; |
419 | } |
420 | |
421 | /////////////////////////////////////////////////////////////////////////////// |
422 | // to_ptr |
423 | // |
424 | template<typename T> |
425 | inline T *&to_ptr(T const &) |
426 | { |
427 | static T *t = 0; |
428 | return t; |
429 | } |
430 | |
431 | // Borland needs a little extra help with arrays |
432 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
433 | template<typename T,std::size_t N> |
434 | inline T (*&to_ptr(T (&)[N]))[N] |
435 | { |
436 | static T (*t)[N] = 0; |
437 | return t; |
438 | } |
439 | |
440 | /////////////////////////////////////////////////////////////////////////////// |
441 | // derefof |
442 | // |
443 | template<typename T> |
444 | inline T &derefof(T *t) |
445 | { |
446 | // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N], |
447 | // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue. |
448 | return reinterpret_cast<T &>( |
449 | *const_cast<char *>( |
450 | reinterpret_cast<char const volatile *>(t) |
451 | ) |
452 | ); |
453 | } |
454 | |
455 | # define BOOST_FOREACH_DEREFOF(T) boost::foreach_detail_::derefof(*T) |
456 | #else |
457 | # define BOOST_FOREACH_DEREFOF(T) (*T) |
458 | #endif |
459 | |
460 | #if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ |
461 | && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
462 | /////////////////////////////////////////////////////////////////////////////// |
463 | // Rvalue references makes it drop-dead simple to detect at compile time |
464 | // whether an expression is an rvalue. |
465 | /////////////////////////////////////////////////////////////////////////////// |
466 | |
467 | # define BOOST_FOREACH_IS_RVALUE(COL) \ |
468 | boost::foreach_detail_::is_rvalue_((COL), 0) |
469 | |
470 | #elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ |
471 | && defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
472 | /////////////////////////////////////////////////////////////////////////////// |
473 | // Detect at compile-time whether an expression yields an rvalue or |
474 | // an lvalue. This is rather non-standard, but some popular compilers |
475 | // accept it. |
476 | /////////////////////////////////////////////////////////////////////////////// |
477 | |
478 | /////////////////////////////////////////////////////////////////////////////// |
479 | // rvalue_probe |
480 | // |
481 | template<typename T> |
482 | struct rvalue_probe |
483 | { |
484 | struct private_type_ {}; |
485 | // can't ever return an array by value |
486 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< |
487 | boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T |
488 | >::type value_type; |
489 | operator value_type() { return *reinterpret_cast<value_type *>(this); } // never called |
490 | operator T &() const { return *reinterpret_cast<T *>(const_cast<rvalue_probe *>(this)); } // never called |
491 | }; |
492 | |
493 | template<typename T> |
494 | rvalue_probe<T> const make_probe(T const &) |
495 | { |
496 | return rvalue_probe<T>(); |
497 | } |
498 | |
499 | # define BOOST_FOREACH_IS_RVALUE(COL) \ |
500 | boost::foreach_detail_::and_( \ |
501 | boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL)) \ |
502 | , (true ? 0 : boost::foreach_detail_::is_rvalue_( \ |
503 | (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0))) |
504 | |
505 | #elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) |
506 | /////////////////////////////////////////////////////////////////////////////// |
507 | // Detect at run-time whether an expression yields an rvalue |
508 | // or an lvalue. This is 100% standard C++, but not all compilers |
509 | // accept it. Also, it causes FOREACH to break when used with non- |
510 | // copyable collection types. |
511 | /////////////////////////////////////////////////////////////////////////////// |
512 | |
513 | /////////////////////////////////////////////////////////////////////////////// |
514 | // rvalue_probe |
515 | // |
516 | template<typename T> |
517 | struct rvalue_probe |
518 | { |
519 | rvalue_probe(T &t, bool &b) |
520 | : value(t) |
521 | , is_rvalue(b) |
522 | { |
523 | } |
524 | |
525 | struct private_type_ {}; |
526 | // can't ever return an array or an abstract type by value |
527 | #ifdef BOOST_NO_IS_ABSTRACT |
528 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< |
529 | boost::is_array<T>, private_type_, T |
530 | >::type value_type; |
531 | #else |
532 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< |
533 | boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T |
534 | >::type value_type; |
535 | #endif |
536 | |
537 | operator value_type() |
538 | { |
539 | this->is_rvalue = true; |
540 | return this->value; |
541 | } |
542 | |
543 | operator T &() const |
544 | { |
545 | return this->value; |
546 | } |
547 | |
548 | private: |
549 | T &value; |
550 | bool &is_rvalue; |
551 | }; |
552 | |
553 | template<typename T> |
554 | rvalue_probe<T> make_probe(T &t, bool &b) { return rvalue_probe<T>(t, b); } |
555 | |
556 | template<typename T> |
557 | rvalue_probe<T const> make_probe(T const &t, bool &b) { return rvalue_probe<T const>(t, b); } |
558 | |
559 | /////////////////////////////////////////////////////////////////////////////// |
560 | // simple_variant |
561 | // holds either a T or a T const* |
562 | template<typename T> |
563 | struct simple_variant |
564 | { |
565 | simple_variant(T const *t) |
566 | : is_rvalue(false) |
567 | { |
568 | *static_cast<T const **>(this->data.address()) = t; |
569 | } |
570 | |
571 | simple_variant(T const &t) |
572 | : is_rvalue(true) |
573 | { |
574 | ::new(this->data.address()) T(t); |
575 | } |
576 | |
577 | simple_variant(simple_variant const &that) |
578 | : is_rvalue(that.is_rvalue) |
579 | { |
580 | if(this->is_rvalue) |
581 | ::new(this->data.address()) T(*that.get()); |
582 | else |
583 | *static_cast<T const **>(this->data.address()) = that.get(); |
584 | } |
585 | |
586 | ~simple_variant() |
587 | { |
588 | if(this->is_rvalue) |
589 | this->get()->~T(); |
590 | } |
591 | |
592 | T const *get() const |
593 | { |
594 | if(this->is_rvalue) |
595 | return static_cast<T const *>(this->data.address()); |
596 | else |
597 | return *static_cast<T const * const *>(this->data.address()); |
598 | } |
599 | |
600 | private: |
601 | enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) }; |
602 | simple_variant &operator =(simple_variant const &); |
603 | bool const is_rvalue; |
604 | aligned_storage<size> data; |
605 | }; |
606 | |
607 | // If the collection is an array or is noncopyable, it must be an lvalue. |
608 | // If the collection is a lightweight proxy, treat it as an rvalue |
609 | // BUGBUG what about a noncopyable proxy? |
610 | template<typename LValue, typename IsProxy> |
611 | inline BOOST_DEDUCED_TYPENAME boost::enable_if<boost::mpl::or_<LValue, IsProxy>, IsProxy>::type * |
612 | should_copy_impl(LValue *, IsProxy *, bool *) |
613 | { |
614 | return 0; |
615 | } |
616 | |
617 | // Otherwise, we must determine at runtime whether it's an lvalue or rvalue |
618 | inline bool * |
619 | should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue) |
620 | { |
621 | return is_rvalue; |
622 | } |
623 | |
624 | #endif |
625 | |
626 | /////////////////////////////////////////////////////////////////////////////// |
627 | // contain |
628 | // |
629 | template<typename T> |
630 | inline auto_any<T> contain(T const &t, boost::mpl::true_ *) // rvalue |
631 | { |
632 | return auto_any<T>(t); |
633 | } |
634 | |
635 | template<typename T> |
636 | inline auto_any<T *> contain(T &t, boost::mpl::false_ *) // lvalue |
637 | { |
638 | // Cannot seem to get sunpro to handle addressof() with array types. |
639 | #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570)) |
640 | return auto_any<T *>(&t); |
641 | #else |
642 | return auto_any<T *>(boost::addressof(t)); |
643 | #endif |
644 | } |
645 | |
646 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
647 | template<typename T> |
648 | inline auto_any<simple_variant<T> > |
649 | contain(T const &t, bool *rvalue) |
650 | { |
651 | return auto_any<simple_variant<T> >(*rvalue ? simple_variant<T>(t) : simple_variant<T>(&t)); |
652 | } |
653 | #endif |
654 | |
655 | ///////////////////////////////////////////////////////////////////////////// |
656 | // begin |
657 | // |
658 | template<typename T, typename C> |
659 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
660 | begin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
661 | { |
662 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
663 | boost::begin(auto_any_cast<T, C>(col))); |
664 | } |
665 | |
666 | template<typename T, typename C> |
667 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
668 | begin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
669 | { |
670 | typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
671 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator; |
672 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
673 | iterator(boost::begin(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
674 | } |
675 | |
676 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
677 | template<typename T> |
678 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type> |
679 | begin(auto_any_t col, type2type<T, const_> *, bool *) |
680 | { |
681 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>( |
682 | boost::begin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
683 | } |
684 | #endif |
685 | |
686 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
687 | template<typename T, typename C> |
688 | inline auto_any<T *> |
689 | begin(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
690 | { |
691 | return auto_any<T *>(auto_any_cast<T *, boost::mpl::false_>(col)); |
692 | } |
693 | #endif |
694 | |
695 | /////////////////////////////////////////////////////////////////////////////// |
696 | // end |
697 | // |
698 | template<typename T, typename C> |
699 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
700 | end(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
701 | { |
702 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
703 | boost::end(auto_any_cast<T, C>(col))); |
704 | } |
705 | |
706 | template<typename T, typename C> |
707 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type> |
708 | end(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
709 | { |
710 | typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
711 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator; |
712 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>( |
713 | iterator(boost::end(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
714 | } |
715 | |
716 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
717 | template<typename T> |
718 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type> |
719 | end(auto_any_t col, type2type<T, const_> *, bool *) |
720 | { |
721 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>( |
722 | boost::end(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
723 | } |
724 | #endif |
725 | |
726 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
727 | template<typename T, typename C> |
728 | inline auto_any<int> |
729 | end(auto_any_t, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
730 | { |
731 | return auto_any<int>(0); // not used |
732 | } |
733 | #endif |
734 | |
735 | /////////////////////////////////////////////////////////////////////////////// |
736 | // done |
737 | // |
738 | template<typename T, typename C> |
739 | inline bool done(auto_any_t cur, auto_any_t end, type2type<T, C> *) |
740 | { |
741 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t; |
742 | return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end); |
743 | } |
744 | |
745 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
746 | template<typename T, typename C> |
747 | inline bool done(auto_any_t cur, auto_any_t, type2type<T *, C> *) // null-terminated C-style strings |
748 | { |
749 | return ! *auto_any_cast<T *, boost::mpl::false_>(cur); |
750 | } |
751 | #endif |
752 | |
753 | /////////////////////////////////////////////////////////////////////////////// |
754 | // next |
755 | // |
756 | template<typename T, typename C> |
757 | inline void next(auto_any_t cur, type2type<T, C> *) |
758 | { |
759 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t; |
760 | ++auto_any_cast<iter_t, boost::mpl::false_>(cur); |
761 | } |
762 | |
763 | /////////////////////////////////////////////////////////////////////////////// |
764 | // deref |
765 | // |
766 | template<typename T, typename C> |
767 | inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type |
768 | deref(auto_any_t cur, type2type<T, C> *) |
769 | { |
770 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t; |
771 | return *auto_any_cast<iter_t, boost::mpl::false_>(cur); |
772 | } |
773 | |
774 | ///////////////////////////////////////////////////////////////////////////// |
775 | // rbegin |
776 | // |
777 | template<typename T, typename C> |
778 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
779 | rbegin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
780 | { |
781 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
782 | boost::rbegin(auto_any_cast<T, C>(col))); |
783 | } |
784 | |
785 | template<typename T, typename C> |
786 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
787 | rbegin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
788 | { |
789 | typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
790 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iterator; |
791 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
792 | iterator(boost::rbegin(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
793 | } |
794 | |
795 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
796 | template<typename T> |
797 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type> |
798 | rbegin(auto_any_t col, type2type<T, const_> *, bool *) |
799 | { |
800 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type>( |
801 | boost::rbegin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
802 | } |
803 | #endif |
804 | |
805 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
806 | template<typename T, typename C> |
807 | inline auto_any<reverse_iterator<T *> > |
808 | rbegin(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
809 | { |
810 | T *p = auto_any_cast<T *, boost::mpl::false_>(col); |
811 | while(0 != *p) |
812 | ++p; |
813 | return auto_any<reverse_iterator<T *> >(reverse_iterator<T *>(p)); |
814 | } |
815 | #endif |
816 | |
817 | /////////////////////////////////////////////////////////////////////////////// |
818 | // rend |
819 | // |
820 | template<typename T, typename C> |
821 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
822 | rend(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue |
823 | { |
824 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
825 | boost::rend(auto_any_cast<T, C>(col))); |
826 | } |
827 | |
828 | template<typename T, typename C> |
829 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type> |
830 | rend(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue |
831 | { |
832 | typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type; |
833 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iterator; |
834 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>( |
835 | iterator(boost::rend(BOOST_FOREACH_DEREFOF((auto_any_cast<type *, boost::mpl::false_>(col)))))); |
836 | } |
837 | |
838 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION |
839 | template<typename T> |
840 | inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type> |
841 | rend(auto_any_t col, type2type<T, const_> *, bool *) |
842 | { |
843 | return auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type>( |
844 | boost::rend(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get())); |
845 | } |
846 | #endif |
847 | |
848 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
849 | template<typename T, typename C> |
850 | inline auto_any<reverse_iterator<T *> > |
851 | rend(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings |
852 | { |
853 | return auto_any<reverse_iterator<T *> >( |
854 | reverse_iterator<T *>(auto_any_cast<T *, boost::mpl::false_>(col))); |
855 | } |
856 | #endif |
857 | |
858 | /////////////////////////////////////////////////////////////////////////////// |
859 | // rdone |
860 | // |
861 | template<typename T, typename C> |
862 | inline bool rdone(auto_any_t cur, auto_any_t end, type2type<T, C> *) |
863 | { |
864 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t; |
865 | return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end); |
866 | } |
867 | |
868 | /////////////////////////////////////////////////////////////////////////////// |
869 | // rnext |
870 | // |
871 | template<typename T, typename C> |
872 | inline void rnext(auto_any_t cur, type2type<T, C> *) |
873 | { |
874 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t; |
875 | ++auto_any_cast<iter_t, boost::mpl::false_>(cur); |
876 | } |
877 | |
878 | /////////////////////////////////////////////////////////////////////////////// |
879 | // rderef |
880 | // |
881 | template<typename T, typename C> |
882 | inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type |
883 | rderef(auto_any_t cur, type2type<T, C> *) |
884 | { |
885 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t; |
886 | return *auto_any_cast<iter_t, boost::mpl::false_>(cur); |
887 | } |
888 | |
889 | } // namespace foreach_detail_ |
890 | } // namespace boost |
891 | |
892 | // Suppress a bogus code analysis warning on vc8+ |
893 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) |
894 | # define BOOST_FOREACH_SUPPRESS_WARNINGS() __pragma(warning(suppress:6001)) |
895 | #else |
896 | # define BOOST_FOREACH_SUPPRESS_WARNINGS() |
897 | #endif |
898 | |
899 | /////////////////////////////////////////////////////////////////////////////// |
900 | // Define a macro for giving hidden variables a unique name. Not strictly |
901 | // needed, but eliminates some warnings on some compilers. |
902 | #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) |
903 | // With some versions of MSVC, use of __LINE__ to create unique identifiers |
904 | // can fail when the Edit-and-Continue debug flag is used. |
905 | # define BOOST_FOREACH_ID(x) x |
906 | #else |
907 | # define BOOST_FOREACH_ID(x) BOOST_PP_CAT(x, __LINE__) |
908 | #endif |
909 | |
910 | // A sneaky way to get the type of the collection without evaluating the expression |
911 | #define BOOST_FOREACH_TYPEOF(COL) \ |
912 | (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL))) |
913 | |
914 | // returns true_* if the type is noncopyable |
915 | #define BOOST_FOREACH_IS_NONCOPYABLE(COL) \ |
916 | boost_foreach_is_noncopyable( \ |
917 | boost::foreach_detail_::to_ptr(COL) \ |
918 | , boost_foreach_argument_dependent_lookup_hack_value) |
919 | |
920 | // returns true_* if the type is a lightweight proxy (and is not noncopyable) |
921 | #define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ |
922 | boost::foreach_detail_::and_( \ |
923 | boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL)) \ |
924 | , boost_foreach_is_lightweight_proxy( \ |
925 | boost::foreach_detail_::to_ptr(COL) \ |
926 | , boost_foreach_argument_dependent_lookup_hack_value)) |
927 | |
928 | #if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) |
929 | /////////////////////////////////////////////////////////////////////////////// |
930 | // R-values and const R-values supported here with zero runtime overhead |
931 | /////////////////////////////////////////////////////////////////////////////// |
932 | |
933 | // No variable is needed to track the rvalue-ness of the collection expression |
934 | # define BOOST_FOREACH_PREAMBLE() \ |
935 | BOOST_FOREACH_SUPPRESS_WARNINGS() |
936 | |
937 | // Evaluate the collection expression |
938 | # define BOOST_FOREACH_EVALUATE(COL) \ |
939 | (COL) |
940 | |
941 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ |
942 | (true ? 0 : boost::foreach_detail_::or_( \ |
943 | BOOST_FOREACH_IS_RVALUE(COL) \ |
944 | , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))) |
945 | |
946 | #elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) |
947 | /////////////////////////////////////////////////////////////////////////////// |
948 | // R-values and const R-values supported here |
949 | /////////////////////////////////////////////////////////////////////////////// |
950 | |
951 | // Declare a variable to track the rvalue-ness of the collection expression |
952 | # define BOOST_FOREACH_PREAMBLE() \ |
953 | BOOST_FOREACH_SUPPRESS_WARNINGS() \ |
954 | if (bool BOOST_FOREACH_ID(_foreach_is_rvalue) = false) {} else |
955 | |
956 | // Evaluate the collection expression, and detect if it is an lvalue or and rvalue |
957 | # define BOOST_FOREACH_EVALUATE(COL) \ |
958 | (true ? boost::foreach_detail_::make_probe((COL), BOOST_FOREACH_ID(_foreach_is_rvalue)) : (COL)) |
959 | |
960 | // The rvalue/lvalue-ness of the collection expression is determined dynamically, unless |
961 | // the type is an array or is noncopyable or is non-const, in which case we know it's an lvalue. |
962 | // If the type happens to be a lightweight proxy, always make a copy. |
963 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ |
964 | (boost::foreach_detail_::should_copy_impl( \ |
965 | true ? 0 : boost::foreach_detail_::or_( \ |
966 | boost::foreach_detail_::is_array_(COL) \ |
967 | , BOOST_FOREACH_IS_NONCOPYABLE(COL) \ |
968 | , boost::foreach_detail_::not_(boost::foreach_detail_::is_const_(COL))) \ |
969 | , true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ |
970 | , &BOOST_FOREACH_ID(_foreach_is_rvalue))) |
971 | |
972 | #elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION) |
973 | /////////////////////////////////////////////////////////////////////////////// |
974 | // R-values supported here, const R-values NOT supported here |
975 | /////////////////////////////////////////////////////////////////////////////// |
976 | |
977 | // No variable is needed to track the rvalue-ness of the collection expression |
978 | # define BOOST_FOREACH_PREAMBLE() \ |
979 | BOOST_FOREACH_SUPPRESS_WARNINGS() |
980 | |
981 | // Evaluate the collection expression |
982 | # define BOOST_FOREACH_EVALUATE(COL) \ |
983 | (COL) |
984 | |
985 | // Determine whether the collection expression is an lvalue or an rvalue. |
986 | // NOTE: this gets the answer wrong for const rvalues. |
987 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ |
988 | (true ? 0 : boost::foreach_detail_::or_( \ |
989 | boost::foreach_detail_::is_rvalue_((COL), 0) \ |
990 | , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))) |
991 | |
992 | #else |
993 | /////////////////////////////////////////////////////////////////////////////// |
994 | // R-values NOT supported here |
995 | /////////////////////////////////////////////////////////////////////////////// |
996 | |
997 | // No variable is needed to track the rvalue-ness of the collection expression |
998 | # define BOOST_FOREACH_PREAMBLE() \ |
999 | BOOST_FOREACH_SUPPRESS_WARNINGS() |
1000 | |
1001 | // Evaluate the collection expression |
1002 | # define BOOST_FOREACH_EVALUATE(COL) \ |
1003 | (COL) |
1004 | |
1005 | // Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies) |
1006 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ |
1007 | (true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)) |
1008 | |
1009 | #endif |
1010 | |
1011 | #define BOOST_FOREACH_CONTAIN(COL) \ |
1012 | boost::foreach_detail_::contain( \ |
1013 | BOOST_FOREACH_EVALUATE(COL) \ |
1014 | , BOOST_FOREACH_SHOULD_COPY(COL)) |
1015 | |
1016 | #define BOOST_FOREACH_BEGIN(COL) \ |
1017 | boost::foreach_detail_::begin( \ |
1018 | BOOST_FOREACH_ID(_foreach_col) \ |
1019 | , BOOST_FOREACH_TYPEOF(COL) \ |
1020 | , BOOST_FOREACH_SHOULD_COPY(COL)) |
1021 | |
1022 | #define BOOST_FOREACH_END(COL) \ |
1023 | boost::foreach_detail_::end( \ |
1024 | BOOST_FOREACH_ID(_foreach_col) \ |
1025 | , BOOST_FOREACH_TYPEOF(COL) \ |
1026 | , BOOST_FOREACH_SHOULD_COPY(COL)) |
1027 | |
1028 | #define BOOST_FOREACH_DONE(COL) \ |
1029 | boost::foreach_detail_::done( \ |
1030 | BOOST_FOREACH_ID(_foreach_cur) \ |
1031 | , BOOST_FOREACH_ID(_foreach_end) \ |
1032 | , BOOST_FOREACH_TYPEOF(COL)) |
1033 | |
1034 | #define BOOST_FOREACH_NEXT(COL) \ |
1035 | boost::foreach_detail_::next( \ |
1036 | BOOST_FOREACH_ID(_foreach_cur) \ |
1037 | , BOOST_FOREACH_TYPEOF(COL)) |
1038 | |
1039 | #define BOOST_FOREACH_DEREF(COL) \ |
1040 | boost::foreach_detail_::deref( \ |
1041 | BOOST_FOREACH_ID(_foreach_cur) \ |
1042 | , BOOST_FOREACH_TYPEOF(COL)) |
1043 | |
1044 | #define BOOST_FOREACH_RBEGIN(COL) \ |
1045 | boost::foreach_detail_::rbegin( \ |
1046 | BOOST_FOREACH_ID(_foreach_col) \ |
1047 | , BOOST_FOREACH_TYPEOF(COL) \ |
1048 | , BOOST_FOREACH_SHOULD_COPY(COL)) |
1049 | |
1050 | #define BOOST_FOREACH_REND(COL) \ |
1051 | boost::foreach_detail_::rend( \ |
1052 | BOOST_FOREACH_ID(_foreach_col) \ |
1053 | , BOOST_FOREACH_TYPEOF(COL) \ |
1054 | , BOOST_FOREACH_SHOULD_COPY(COL)) |
1055 | |
1056 | #define BOOST_FOREACH_RDONE(COL) \ |
1057 | boost::foreach_detail_::rdone( \ |
1058 | BOOST_FOREACH_ID(_foreach_cur) \ |
1059 | , BOOST_FOREACH_ID(_foreach_end) \ |
1060 | , BOOST_FOREACH_TYPEOF(COL)) |
1061 | |
1062 | #define BOOST_FOREACH_RNEXT(COL) \ |
1063 | boost::foreach_detail_::rnext( \ |
1064 | BOOST_FOREACH_ID(_foreach_cur) \ |
1065 | , BOOST_FOREACH_TYPEOF(COL)) |
1066 | |
1067 | #define BOOST_FOREACH_RDEREF(COL) \ |
1068 | boost::foreach_detail_::rderef( \ |
1069 | BOOST_FOREACH_ID(_foreach_cur) \ |
1070 | , BOOST_FOREACH_TYPEOF(COL)) |
1071 | |
1072 | /////////////////////////////////////////////////////////////////////////////// |
1073 | // BOOST_FOREACH |
1074 | // |
1075 | // For iterating over collections. Collections can be |
1076 | // arrays, null-terminated strings, or STL containers. |
1077 | // The loop variable can be a value or reference. For |
1078 | // example: |
1079 | // |
1080 | // std::list<int> int_list(/*stuff*/); |
1081 | // BOOST_FOREACH(int &i, int_list) |
1082 | // { |
1083 | // /* |
1084 | // * loop body goes here. |
1085 | // * i is a reference to the int in int_list. |
1086 | // */ |
1087 | // } |
1088 | // |
1089 | // Alternately, you can declare the loop variable first, |
1090 | // so you can access it after the loop finishes. Obviously, |
1091 | // if you do it this way, then the loop variable cannot be |
1092 | // a reference. |
1093 | // |
1094 | // int i; |
1095 | // BOOST_FOREACH(i, int_list) |
1096 | // { ... } |
1097 | // |
1098 | #define BOOST_FOREACH(VAR, COL) \ |
1099 | BOOST_FOREACH_PREAMBLE() \ |
1100 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ |
1101 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \ |
1102 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \ |
1103 | for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ |
1104 | BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \ |
1105 | BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \ |
1106 | if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ |
1107 | for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) |
1108 | |
1109 | /////////////////////////////////////////////////////////////////////////////// |
1110 | // BOOST_REVERSE_FOREACH |
1111 | // |
1112 | // For iterating over collections in reverse order. In |
1113 | // all other respects, BOOST_REVERSE_FOREACH is like |
1114 | // BOOST_FOREACH. |
1115 | // |
1116 | #define BOOST_REVERSE_FOREACH(VAR, COL) \ |
1117 | BOOST_FOREACH_PREAMBLE() \ |
1118 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ |
1119 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) {} else \ |
1120 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL)) {} else \ |
1121 | for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ |
1122 | BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_RDONE(COL); \ |
1123 | BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \ |
1124 | if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ |
1125 | for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) |
1126 | |
1127 | #endif |
1128 | |