]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |