Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/foreach.hpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 30.4 KB
Line 
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//
9// Credits:
10//  Anson Tsao        - for the initial inspiration and several good suggestions.
11//  Thorsten Ottosen  - for Boost.Range, and for suggesting a way to detect
12//                      const-qualified rvalues at compile time on VC7.1+
13//  Russell Hind      - For help porting to Borland
14//  Alisdair Meredith - For help porting to Borland
15//  Stefan Slapeta    - For help porting to Intel
16
17#ifndef BOOST_FOREACH
18
19// MS compatible compilers support #pragma once
20#if defined(_MSC_VER) && (_MSC_VER >= 1020)
21# pragma once
22#endif
23
24#include <cstddef>
25#include <utility>  // for std::pair
26
27#include <boost/config.hpp>
28#include <boost/detail/workaround.hpp>
29
30// Some compilers let us detect even const-qualified rvalues at compile-time
31#if BOOST_WORKAROUND(BOOST_MSVC, >= 1310)                                                       \
32 || (BOOST_WORKAROUND(__GNUC__, >= 4) && !defined(BOOST_INTEL))                                 \
33 || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL))
34# define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
35#else
36// Some compilers allow temporaries to be bound to non-const references.
37// These compilers make it impossible to for BOOST_FOREACH to detect
38// temporaries and avoid reevaluation of the collection expression.
39# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)                                                      \
40  || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))                                     \
41  || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))                   \
42  || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570))                                      \
43  || BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
44#  define BOOST_FOREACH_NO_RVALUE_DETECTION
45# endif
46// Some compilers do not correctly implement the lvalue/rvalue conversion
47// rules of the ternary conditional operator.
48# if defined(BOOST_FOREACH_NO_RVALUE_DETECTION)                                                 \
49  || defined(BOOST_NO_SFINAE)                                                                   \
50  || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))                                        \
51  || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 810)                                                  \
52  || BOOST_WORKAROUND(__GNUC__, < 3)                                                            \
53  || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 2))                                \
54  || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__))       \
55  || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))                                         \
56  || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
57#  define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
58# else
59#  define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
60# endif
61#endif
62
63#include <boost/mpl/if.hpp>
64#include <boost/mpl/logical.hpp>
65#include <boost/mpl/eval_if.hpp>
66#include <boost/noncopyable.hpp>
67#include <boost/range/end.hpp>
68#include <boost/range/begin.hpp>
69#include <boost/range/result_iterator.hpp>
70#include <boost/type_traits/is_array.hpp>
71#include <boost/type_traits/is_const.hpp>
72#include <boost/type_traits/is_abstract.hpp>
73#include <boost/type_traits/is_base_and_derived.hpp>
74#include <boost/iterator/iterator_traits.hpp>
75#include <boost/utility/addressof.hpp>
76
77#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
78# include <new>
79# include <boost/aligned_storage.hpp>
80# include <boost/utility/enable_if.hpp>
81# include <boost/type_traits/remove_const.hpp>
82#endif
83
84// This must be at global scope, hence the uglified name
85enum boost_foreach_argument_dependent_lookup_hack
86{
87    boost_foreach_argument_dependent_lookup_hack_value
88};
89
90namespace boost
91{
92
93// forward declarations for iterator_range
94template<typename T>
95class iterator_range;
96
97// forward declarations for sub_range
98template<typename T>
99class sub_range;
100
101namespace foreach
102{
103    ///////////////////////////////////////////////////////////////////////////////
104    // in_range
105    //
106    template<typename T>
107    inline std::pair<T, T> in_range(T begin, T end)
108    {
109        return std::make_pair(begin, end);
110    }
111
112    ///////////////////////////////////////////////////////////////////////////////
113    // boost::foreach::tag
114    //
115    typedef boost_foreach_argument_dependent_lookup_hack tag;
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.
164template<typename T>
165inline boost::foreach::is_lightweight_proxy<T> *
166boost_foreach_is_lightweight_proxy(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; }
167
168template<typename T>
169inline boost::mpl::true_ *
170boost_foreach_is_lightweight_proxy(std::pair<T, T> *&, boost::foreach::tag) { return 0; }
171
172template<typename T>
173inline boost::mpl::true_ *
174boost_foreach_is_lightweight_proxy(boost::iterator_range<T> *&, boost::foreach::tag) { return 0; }
175
176template<typename T>
177inline boost::mpl::true_ *
178boost_foreach_is_lightweight_proxy(boost::sub_range<T> *&, boost::foreach::tag) { return 0; }
179
180template<typename T>
181inline boost::mpl::true_ *
182boost_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.
189template<typename T>
190inline boost::foreach::is_noncopyable<T> *
191boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; }
192
193namespace boost
194{
195
196namespace foreach_detail_
197{
198
199///////////////////////////////////////////////////////////////////////////////
200// Define some utilities for assessing the properties of expressions
201//
202typedef char yes_type;
203typedef char (&no_type)[2];
204yes_type is_true(boost::mpl::true_ *);
205no_type is_true(boost::mpl::false_ *);
206
207// Extracts the desired property from the expression without evaluating it
208#define BOOST_FOREACH_PROTECT(expr)                                                             \
209    (static_cast<boost::mpl::bool_<1 == sizeof(boost::foreach_detail_::is_true(expr))> *>(0))
210
211template<typename Bool1, typename Bool2>
212inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; }
213
214template<typename Bool1, typename Bool2, typename Bool3>
215inline boost::mpl::and_<Bool1, Bool2, Bool3> *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; }
216
217template<typename Bool1, typename Bool2>
218inline boost::mpl::or_<Bool1, Bool2> *or_(Bool1 *, Bool2 *) { return 0; }
219
220template<typename Bool1, typename Bool2, typename Bool3>
221inline boost::mpl::or_<Bool1, Bool2, Bool3> *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; }
222
223template<typename Bool>
224inline boost::mpl::not_<Bool> *not_(Bool *) { return 0; }
225
226template<typename T>
227inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; }
228
229template<typename T>
230inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; }
231
232template<typename T>
233inline boost::is_array<T> *is_array_(T const &) { return 0; }
234
235template<typename T>
236inline boost::is_const<T> *is_const_(T &) { return 0; }
237
238#ifndef BOOST_FOREACH_NO_RVALUE_DETECTION
239template<typename T>
240inline boost::mpl::true_ *is_const_(T const &) { return 0; }
241#endif
242
243///////////////////////////////////////////////////////////////////////////////
244// auto_any_t/auto_any
245//  General utility for putting an object of any type into automatic storage
246struct auto_any_base
247{
248    // auto_any_base must evaluate to false in boolean context so that
249    // they can be declared in if() statements.
250    operator bool() const
251    {
252        return false;
253    }
254};
255
256template<typename T>
257struct auto_any : auto_any_base
258{
259    auto_any(T const &t)
260      : item(t)
261    {
262    }
263
264    // temporaries of type auto_any will be bound to const auto_any_base
265    // references, but we still want to be able to mutate the stored
266    // data, so declare it as mutable.
267    mutable T item;
268};
269
270typedef auto_any_base const &auto_any_t;
271
272template<typename T, typename C>
273inline BOOST_DEDUCED_TYPENAME boost::mpl::if_<C, T const, T>::type &auto_any_cast(auto_any_t a)
274{
275    return static_cast<auto_any<T> const &>(a).item;
276}
277
278typedef boost::mpl::true_ const_;
279
280///////////////////////////////////////////////////////////////////////////////
281// type2type
282//
283template<typename T, typename C = boost::mpl::false_>
284struct type2type
285  : boost::mpl::if_<C, T const, T>
286{
287};
288
289template<typename T, typename C = boost::mpl::false_>
290struct foreach_iterator
291{
292    typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
293        C
294      , range_const_iterator<T>
295      , range_iterator<T>
296    >::type type;
297};
298
299template<typename T, typename C = boost::mpl::false_>
300struct foreach_reference
301  : iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
302{
303};
304
305///////////////////////////////////////////////////////////////////////////////
306// encode_type
307//
308template<typename T>
309inline type2type<T> *encode_type(T &, boost::mpl::false_ *) { return 0; }
310
311template<typename T>
312inline type2type<T, const_> *encode_type(T const &, boost::mpl::true_ *) { return 0; }
313
314///////////////////////////////////////////////////////////////////////////////
315// set_false
316//
317inline bool set_false(bool &b) { return b = false; }
318
319///////////////////////////////////////////////////////////////////////////////
320// to_ptr
321//
322template<typename T>
323inline T *&to_ptr(T const &)
324{
325    static T *t = 0;
326    return t;
327}
328
329// Borland needs a little extra help with arrays
330#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
331template<typename T,std::size_t N>
332inline T (*&to_ptr(T (&)[N]))[N]
333{
334    static T (*t)[N] = 0;
335    return t;
336}
337#endif
338
339///////////////////////////////////////////////////////////////////////////////
340// derefof
341//
342template<typename T>
343inline T &derefof(T *t)
344{
345    // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N],
346    // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue.
347    return reinterpret_cast<T &>(
348        *const_cast<char *>(
349            reinterpret_cast<char const volatile *>(t)
350        )
351    );
352}
353
354#ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
355///////////////////////////////////////////////////////////////////////////////
356// Detect at compile-time whether an expression yields an rvalue or
357// an lvalue. This is rather non-standard, but some popular compilers
358// accept it.
359///////////////////////////////////////////////////////////////////////////////
360
361///////////////////////////////////////////////////////////////////////////////
362// rvalue_probe
363//
364template<typename T>
365struct rvalue_probe
366{
367    struct private_type_ {};
368    // can't ever return an array by value
369    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
370        boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T
371    >::type value_type;
372    operator value_type();
373    operator T &() const;
374};
375
376template<typename T>
377rvalue_probe<T> const make_probe(T const &t);
378
379# define BOOST_FOREACH_IS_RVALUE(COL)                                                           \
380    boost::foreach_detail_::and_(                                                               \
381        boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL))                    \
382      , BOOST_FOREACH_PROTECT(boost::foreach_detail_::is_rvalue_(                               \
383            (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0)))
384
385#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
386///////////////////////////////////////////////////////////////////////////////
387// Detect at run-time whether an expression yields an rvalue
388// or an lvalue. This is 100% standard C++, but not all compilers
389// accept it. Also, it causes FOREACH to break when used with non-
390// copyable collection types.
391///////////////////////////////////////////////////////////////////////////////
392
393///////////////////////////////////////////////////////////////////////////////
394// rvalue_probe
395//
396template<typename T>
397struct rvalue_probe
398{
399    rvalue_probe(T &t, bool &b)
400      : value(t)
401      , is_rvalue(b)
402    {
403    }
404
405    struct private_type_ {};
406    // can't ever return an array or an abstract type by value
407    #ifdef BOOST_NO_IS_ABSTRACT
408    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
409        boost::is_array<T>, private_type_, T
410    >::type value_type;
411    #else
412    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
413        boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T
414    >::type value_type;
415    #endif
416   
417    operator value_type()
418    {
419        this->is_rvalue = true;
420        return this->value;
421    }
422
423    operator T &() const
424    {
425        return this->value;
426    }
427
428private:
429    T &value;
430    bool &is_rvalue;
431};
432
433template<typename T>
434rvalue_probe<T> make_probe(T &t, bool &b) { return rvalue_probe<T>(t, b); }
435
436template<typename T>
437rvalue_probe<T const> make_probe(T const &t, bool &b)  { return rvalue_probe<T const>(t, b); }
438
439///////////////////////////////////////////////////////////////////////////////
440// simple_variant
441//  holds either a T or a T const*
442template<typename T>
443struct simple_variant
444{
445    simple_variant(T const *t)
446      : is_rvalue(false)
447    {
448        *static_cast<T const **>(this->data.address()) = t;
449    }
450
451    simple_variant(T const &t)
452      : is_rvalue(true)
453    {
454        ::new(this->data.address()) T(t);
455    }
456
457    simple_variant(simple_variant const &that)
458      : is_rvalue(that.is_rvalue)
459    {
460        if(this->is_rvalue)
461            ::new(this->data.address()) T(*that.get());
462        else
463            *static_cast<T const **>(this->data.address()) = that.get();
464    }
465
466    ~simple_variant()
467    {
468        if(this->is_rvalue)
469            this->get()->~T();
470    }
471
472    T const *get() const
473    {
474        if(this->is_rvalue)
475            return static_cast<T const *>(this->data.address());
476        else
477            return *static_cast<T const * const *>(this->data.address());
478    }
479
480private:
481    enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) };
482    simple_variant &operator =(simple_variant const &); 
483    bool const is_rvalue;
484    aligned_storage<size> data;
485};
486
487// If the collection is an array or is noncopyable, it must be an lvalue.
488// If the collection is a lightweight proxy, treat it as an rvalue
489// BUGBUG what about a noncopyable proxy?
490template<typename LValue, typename IsProxy>
491inline BOOST_DEDUCED_TYPENAME boost::enable_if<boost::mpl::or_<LValue, IsProxy>, IsProxy>::type *
492should_copy_impl(LValue *, IsProxy *, bool *)
493{
494    return 0;
495}
496
497// Otherwise, we must determine at runtime whether it's an lvalue or rvalue
498inline bool *
499should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue)
500{
501    return is_rvalue;
502}
503
504#endif
505
506///////////////////////////////////////////////////////////////////////////////
507// contain
508//
509template<typename T>
510inline auto_any<T> contain(T const &t, boost::mpl::true_ *) // rvalue
511{
512    return t;
513}
514
515template<typename T>
516inline auto_any<T *> contain(T &t, boost::mpl::false_ *) // lvalue
517{
518    // Cannot seem to get sunpro to handle addressof() with array types.
519    #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570))
520    return &t;
521    #else
522    return boost::addressof(t);
523    #endif
524}
525
526#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
527template<typename T>
528auto_any<simple_variant<T> >
529contain(T const &t, bool *rvalue)
530{
531    return *rvalue ? simple_variant<T>(t) : simple_variant<T>(&t);
532}
533#endif
534
535/////////////////////////////////////////////////////////////////////////////
536// begin
537//
538template<typename T, typename C>
539inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
540begin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
541{
542    return boost::begin(auto_any_cast<T, C>(col));
543}
544
545template<typename T, typename C>
546inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
547begin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
548{
549    typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
550    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator;
551    return iterator(boost::begin(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
552}
553
554#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
555template<typename T>
556auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>
557begin(auto_any_t col, type2type<T, const_> *, bool *)
558{
559    return boost::begin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
560}
561#endif
562
563///////////////////////////////////////////////////////////////////////////////
564// end
565//
566template<typename T, typename C>
567inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
568end(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
569{
570    return boost::end(auto_any_cast<T, C>(col));
571}
572
573template<typename T, typename C>
574inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
575end(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
576{
577    typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
578    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator;
579    return iterator(boost::end(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
580}
581
582#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
583template<typename T>
584auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>
585end(auto_any_t col, type2type<T, const_> *, bool *)
586{
587    return boost::end(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
588}
589#endif
590
591#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
592template<typename T, typename C>
593inline auto_any<int>
594end(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings
595{
596    return 0; // not used
597}
598#endif
599
600///////////////////////////////////////////////////////////////////////////////
601// done
602//
603template<typename T, typename C>
604inline bool done(auto_any_t cur, auto_any_t end, type2type<T, C> *)
605{
606    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
607    return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end);
608}
609
610#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
611template<typename T, typename C>
612inline bool done(auto_any_t cur, auto_any_t, type2type<T *, C> *) // null-terminated C-style strings
613{
614    return ! *auto_any_cast<T *, boost::mpl::false_>(cur);
615}
616#endif
617
618///////////////////////////////////////////////////////////////////////////////
619// next
620//
621template<typename T, typename C>
622inline void next(auto_any_t cur, type2type<T, C> *)
623{
624    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
625    ++auto_any_cast<iter_t, boost::mpl::false_>(cur);
626}
627
628///////////////////////////////////////////////////////////////////////////////
629// deref
630//
631template<typename T, typename C>
632inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type
633deref(auto_any_t cur, type2type<T, C> *)
634{
635    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
636    return *auto_any_cast<iter_t, boost::mpl::false_>(cur);
637}
638
639} // namespace foreach_detail_
640} // namespace boost
641
642// A sneaky way to get the type of the collection without evaluating the expression
643#define BOOST_FOREACH_TYPEOF(COL)                                                               \
644    (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL)))
645
646// returns true_* if the type is noncopyable
647#define BOOST_FOREACH_IS_NONCOPYABLE(COL)                                                       \
648    boost_foreach_is_noncopyable(                                                               \
649        boost::foreach_detail_::to_ptr(COL)                                                     \
650      , boost_foreach_argument_dependent_lookup_hack_value)
651
652// returns true_* if the type is a lightweight proxy (and is not noncopyable)
653#define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)                                                 \
654    boost::foreach_detail_::and_(                                                               \
655        boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL))                         \
656      , boost_foreach_is_lightweight_proxy(                                                     \
657            boost::foreach_detail_::to_ptr(COL)                                                 \
658          , boost_foreach_argument_dependent_lookup_hack_value))
659
660#ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
661///////////////////////////////////////////////////////////////////////////////
662// R-values and const R-values supported here with zero runtime overhead
663///////////////////////////////////////////////////////////////////////////////
664
665// No variable is needed to track the rvalue-ness of the collection expression
666# define BOOST_FOREACH_PREAMBLE()                                                               \
667    /**/
668
669// Evaluate the collection expression
670# define BOOST_FOREACH_EVALUATE(COL)                                                            \
671    (COL)
672
673# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
674    (true ? 0 : boost::foreach_detail_::or_(                                                    \
675        BOOST_FOREACH_IS_RVALUE(COL)                                                            \
676      , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
677
678#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
679///////////////////////////////////////////////////////////////////////////////
680// R-values and const R-values supported here
681///////////////////////////////////////////////////////////////////////////////
682
683// Declare a variable to track the rvalue-ness of the collection expression
684# define BOOST_FOREACH_PREAMBLE()                                                               \
685    if (bool _foreach_is_rvalue = false) {} else
686
687// Evaluate the collection expression, and detect if it is an lvalue or and rvalue
688# define BOOST_FOREACH_EVALUATE(COL)                                                            \
689    (true ? boost::foreach_detail_::make_probe((COL), _foreach_is_rvalue) : (COL))
690
691// The rvalue/lvalue-ness of the collection expression is determined dynamically, unless
692// type type is an array or is noncopyable or is non-const, in which case we know it's an lvalue.
693// If the type happens to be a lightweight proxy, always make a copy.
694# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
695    (boost::foreach_detail_::should_copy_impl(                                                  \
696        true ? 0 : boost::foreach_detail_::or_(                                                 \
697            boost::foreach_detail_::is_array_(COL)                                              \
698          , BOOST_FOREACH_IS_NONCOPYABLE(COL)                                                   \
699          , boost::foreach_detail_::not_(boost::foreach_detail_::is_const_(COL)))               \
700      , true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)                                      \
701      , &_foreach_is_rvalue))
702
703#elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION)
704///////////////////////////////////////////////////////////////////////////////
705// R-values supported here, const R-values NOT supported here
706///////////////////////////////////////////////////////////////////////////////
707
708// No variable is needed to track the rvalue-ness of the collection expression
709# define BOOST_FOREACH_PREAMBLE()                                                               \
710    /**/
711
712// Evaluate the collection expression
713# define BOOST_FOREACH_EVALUATE(COL)                                                            \
714    (COL)
715
716// Determine whether the collection expression is an lvalue or an rvalue.
717// NOTE: this gets the answer wrong for const rvalues.
718# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
719    (true ? 0 : boost::foreach_detail_::or_(                                                    \
720        boost::foreach_detail_::is_rvalue_((COL), 0)                                            \
721      , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
722
723#else
724///////////////////////////////////////////////////////////////////////////////
725// R-values NOT supported here
726///////////////////////////////////////////////////////////////////////////////
727
728// No variable is needed to track the rvalue-ness of the collection expression
729# define BOOST_FOREACH_PREAMBLE()                                                               \
730    /**/
731
732// Evaluate the collection expression
733# define BOOST_FOREACH_EVALUATE(COL)                                                            \
734    (COL)
735
736// Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies)
737# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
738    (true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))
739
740#endif
741
742#define BOOST_FOREACH_CONTAIN(COL)                                                              \
743    boost::foreach_detail_::contain(                                                            \
744        BOOST_FOREACH_EVALUATE(COL)                                                             \
745      , BOOST_FOREACH_SHOULD_COPY(COL))
746
747#define BOOST_FOREACH_BEGIN(COL)                                                                \
748    boost::foreach_detail_::begin(                                                              \
749        _foreach_col                                                                            \
750      , BOOST_FOREACH_TYPEOF(COL)                                                               \
751      , BOOST_FOREACH_SHOULD_COPY(COL))
752
753#define BOOST_FOREACH_END(COL)                                                                  \
754    boost::foreach_detail_::end(                                                                \
755        _foreach_col                                                                            \
756      , BOOST_FOREACH_TYPEOF(COL)                                                               \
757      , BOOST_FOREACH_SHOULD_COPY(COL))
758
759#define BOOST_FOREACH_DONE(COL)                                                                 \
760    boost::foreach_detail_::done(                                                               \
761        _foreach_cur                                                                            \
762      , _foreach_end                                                                            \
763      , BOOST_FOREACH_TYPEOF(COL))
764
765#define BOOST_FOREACH_NEXT(COL)                                                                 \
766    boost::foreach_detail_::next(                                                               \
767        _foreach_cur                                                                            \
768      , BOOST_FOREACH_TYPEOF(COL))
769
770#define BOOST_FOREACH_DEREF(COL)                                                                \
771    boost::foreach_detail_::deref(                                                              \
772        _foreach_cur                                                                            \
773      , BOOST_FOREACH_TYPEOF(COL))
774
775///////////////////////////////////////////////////////////////////////////////
776// BOOST_FOREACH
777//
778//   For iterating over collections. Collections can be
779//   arrays, null-terminated strings, or STL containers.
780//   The loop variable can be a value or reference. For
781//   example:
782//
783//   std::list<int> int_list(/*stuff*/);
784//   BOOST_FOREACH(int &i, int_list)
785//   {
786//       /*
787//        * loop body goes here.
788//        * i is a reference to the int in int_list.
789//        */
790//   }
791//
792//   Alternately, you can declare the loop variable first,
793//   so you can access it after the loop finishes. Obviously,
794//   if you do it this way, then the loop variable cannot be
795//   a reference.
796//
797//   int i;
798//   BOOST_FOREACH(i, int_list)
799//       { ... }
800//
801#define BOOST_FOREACH(VAR, COL)                                                                 \
802    BOOST_FOREACH_PREAMBLE()                                                                    \
803    if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else   \
804    if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else     \
805    if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else       \
806    for (bool _foreach_continue = true;                                                         \
807              _foreach_continue && !BOOST_FOREACH_DONE(COL);                                    \
808              _foreach_continue ? BOOST_FOREACH_NEXT(COL) : (void)0)                            \
809        if  (boost::foreach_detail_::set_false(_foreach_continue)) {} else                      \
810        for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true)
811
812#endif
Note: See TracBrowser for help on using the repository browser.