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