foreach.hpp

Go to the documentation of this file.
00001 ///////////////////////////////////////////////////////////////////////////////
00002 // foreach.hpp header file
00003 //
00004 // Copyright 2004 Eric Niebler.
00005 // Distributed under the Boost Software License, Version 1.0. (See
00006 // accompanying file LICENSE_1_0.txt or copy at
00007 // http://www.boost.org/LICENSE_1_0.txt)
00008 //
00009 
00010 #ifndef BOOST_FOREACH
00011 
00012 // MS compatible compilers support #pragma once
00013 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00014 # pragma once
00015 #endif
00016 
00017 #include <cstddef>
00018 #include <utility>  // for std::pair
00019 
00020 #include <boost/config.hpp>
00021 #include <boost/detail/workaround.hpp>
00022 
00023 // Some compilers let us detect even const-qualified rvalues at compile-time
00024 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1310)                                                       \
00025  || BOOST_WORKAROUND(__GNUC__, >= 4)                                                            \
00026  || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4))
00027 # define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
00028 #else
00029 // Some compilers allow temporaries to be bound to non-const references.
00030 // These compilers make it impossible to for BOOST_FOREACH to detect
00031 // temporaries and avoid reevaluation of the collection expression.
00032 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)                                                      \
00033   || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))                                     \
00034   || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))                   \
00035   || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570))                                      \
00036   || BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
00037 #  define BOOST_FOREACH_NO_RVALUE_DETECTION
00038 # endif
00039 // Some compilers do not correctly implement the lvalue/rvalue conversion
00040 // rules of the ternary conditional operator.
00041 # if defined(BOOST_FOREACH_NO_RVALUE_DETECTION)                                                 \
00042   || defined(BOOST_NO_SFINAE)                                                                   \
00043   || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))                                        \
00044   || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 810)                                                  \
00045   || BOOST_WORKAROUND(__GNUC__, < 3)                                                            \
00046   || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 2))                                \
00047   || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__))       \
00048   || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))                                         \
00049   || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
00050 #  define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
00051 # else
00052 #  define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
00053 # endif
00054 #endif
00055 
00056 #include <boost/mpl/if.hpp>
00057 #include <boost/mpl/logical.hpp>
00058 #include <boost/mpl/eval_if.hpp>
00059 #include <boost/noncopyable.hpp>
00060 #include <boost/range/end.hpp>
00061 #include <boost/range/begin.hpp>
00062 #include <boost/range/result_iterator.hpp>
00063 #include <boost/type_traits/is_array.hpp>
00064 #include <boost/type_traits/is_const.hpp>
00065 #include <boost/type_traits/is_base_and_derived.hpp>
00066 #include <boost/iterator/iterator_traits.hpp>
00067 #include <boost/utility/addressof.hpp>
00068 
00069 #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
00070 # include <new>
00071 # include <boost/aligned_storage.hpp>
00072 # include <boost/utility/enable_if.hpp>
00073 # include <boost/type_traits/remove_const.hpp>
00074 #endif
00075 
00076 // This must be at global scope, hence the uglified name
00077 enum boost_foreach_argument_dependent_lookup_hack
00078 {
00079     boost_foreach_argument_dependent_lookup_hack_value
00080 };
00081 
00082 namespace boost
00083 {
00084 
00085 // forward declarations for iterator_range
00086 template<typename T>
00087 class iterator_range;
00088 
00089 // forward declarations for sub_range
00090 template<typename T>
00091 class sub_range;
00092 
00093 namespace foreach
00094 {
00095     ///////////////////////////////////////////////////////////////////////////////
00096     // in_range
00097     //
00098     template<typename T>
00099     inline std::pair<T, T> in_range(T begin, T end)
00100     {
00101         return std::make_pair(begin, end);
00102     }
00103 
00104     ///////////////////////////////////////////////////////////////////////////////
00105     // boost::foreach::tag
00106     //
00107     typedef boost_foreach_argument_dependent_lookup_hack tag;
00108 
00109     ///////////////////////////////////////////////////////////////////////////////
00110     // boost::foreach::is_lightweight_proxy
00111     //   Specialize this for user-defined collection types if they are inexpensive to copy.
00112     //   This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff.
00113     template<typename T>
00114     struct is_lightweight_proxy
00115       : boost::mpl::false_
00116     {
00117     };
00118 
00119     ///////////////////////////////////////////////////////////////////////////////
00120     // boost::foreach::is_noncopyable
00121     //   Specialize this for user-defined collection types if they cannot be copied.
00122     //   This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff.
00123     template<typename T>
00124     struct is_noncopyable
00125     #ifndef BOOST_BROKEN_IS_BASE_AND_DERIVED
00126       : boost::is_base_and_derived<boost::noncopyable, T>
00127     #else
00128       : boost::mpl::false_
00129     #endif
00130     {
00131     };
00132 
00133 } // namespace foreach
00134 
00135 } // namespace boost
00136 
00137 ///////////////////////////////////////////////////////////////////////////////
00138 // boost_foreach_is_lightweight_proxy
00139 //   Another customization point for the is_lightweight_proxy optimization,
00140 //   this one works on legacy compilers. Overload boost_foreach_is_lightweight_proxy
00141 //   at the global namespace for your type.
00142 template<typename T>
00143 inline boost::foreach::is_lightweight_proxy<T> *
00144 boost_foreach_is_lightweight_proxy(T *&, ...) { return 0; }
00145 
00146 template<typename T>
00147 inline boost::mpl::true_ *
00148 boost_foreach_is_lightweight_proxy(std::pair<T, T> *&, boost::foreach::tag) { return 0; }
00149 
00150 template<typename T>
00151 inline boost::mpl::true_ *
00152 boost_foreach_is_lightweight_proxy(boost::iterator_range<T> *&, boost::foreach::tag) { return 0; }
00153 
00154 template<typename T>
00155 inline boost::mpl::true_ *
00156 boost_foreach_is_lightweight_proxy(boost::sub_range<T> *&, boost::foreach::tag) { return 0; }
00157 
00158 template<typename T>
00159 inline boost::mpl::true_ *
00160 boost_foreach_is_lightweight_proxy(T **, boost::foreach::tag) { return 0; }
00161 
00162 template<typename T, std::size_t N>
00163 inline boost::mpl::false_ *
00164 boost_foreach_is_lightweight_proxy(T (*)[N], boost::foreach::tag) { return 0; }
00165 
00166 ///////////////////////////////////////////////////////////////////////////////
00167 // boost_foreach_is_noncopyable
00168 //   Another customization point for the is_noncopyable trait,
00169 //   this one works on legacy compilers. Overload boost_foreach_is_noncopyable
00170 //   at the global namespace for your type.
00171 template<typename T>
00172 inline boost::foreach::is_noncopyable<T> *
00173 boost_foreach_is_noncopyable(T *&, ...) { return 0; }
00174 
00175 namespace boost
00176 {
00177 
00178 namespace foreach_detail_
00179 {
00180 
00181 ///////////////////////////////////////////////////////////////////////////////
00182 // Define some utilities for assessing the properties of expressions
00183 //
00184 typedef char yes_type;
00185 typedef char (&no_type)[2];
00186 yes_type is_true(boost::mpl::true_ *);
00187 no_type is_true(boost::mpl::false_ *);
00188 
00189 // Extracts the desired property from the expression without evaluating it
00190 #define BOOST_FOREACH_PROTECT(expr)                                                             \
00191     (static_cast<boost::mpl::bool_<1 == sizeof(boost::foreach_detail_::is_true(expr))> *>(0))
00192 
00193 template<typename Bool1, typename Bool2>
00194 inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; }
00195 
00196 template<typename Bool1, typename Bool2, typename Bool3>
00197 inline boost::mpl::and_<Bool1, Bool2, Bool3> *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; }
00198 
00199 template<typename Bool1, typename Bool2>
00200 inline boost::mpl::or_<Bool1, Bool2> *or_(Bool1 *, Bool2 *) { return 0; }
00201 
00202 template<typename Bool1, typename Bool2, typename Bool3>
00203 inline boost::mpl::or_<Bool1, Bool2, Bool3> *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; }
00204 
00205 template<typename Bool>
00206 inline boost::mpl::not_<Bool> *not_(Bool *) { return 0; }
00207 
00208 template<typename T>
00209 inline boost::mpl::false_ *is_rvalue(T &, int) { return 0; }
00210 
00211 template<typename T>
00212 inline boost::mpl::true_ *is_rvalue(T const &, ...) { return 0; }
00213 
00214 template<typename T>
00215 inline boost::is_array<T> *is_array(T const &) { return 0; }
00216 
00217 template<typename T>
00218 inline boost::is_const<T> *is_const(T &) { return 0; }
00219 
00220 #ifndef BOOST_FOREACH_NO_RVALUE_DETECTION
00221 template<typename T>
00222 inline boost::mpl::true_ *is_const(T const &) { return 0; }
00223 #endif
00224 
00225 ///////////////////////////////////////////////////////////////////////////////
00226 // auto_any_t/auto_any
00227 //  General utility for putting an object of any type into automatic storage
00228 struct auto_any_base
00229 {
00230     // auto_any_base must evaluate to false in boolean context so that
00231     // they can be declared in if() statements.
00232     operator bool() const
00233     {
00234         return false;
00235     }
00236 };
00237 
00238 template<typename T>
00239 struct auto_any : auto_any_base
00240 {
00241     auto_any(T const &t)
00242       : item(t)
00243     {
00244     }
00245 
00246     // temporaries of type auto_any will be bound to const auto_any_base
00247     // references, but we still want to be able to mutate the stored
00248     // data, so declare it as mutable.
00249     mutable T item;
00250 };
00251 
00252 typedef auto_any_base const &auto_any_t;
00253 
00254 template<typename T, typename C>
00255 inline BOOST_DEDUCED_TYPENAME boost::mpl::if_<C, T const, T>::type &auto_any_cast(auto_any_t a)
00256 {
00257     return static_cast<auto_any<T> const &>(a).item;
00258 }
00259 
00260 typedef boost::mpl::true_ const_;
00261 
00262 ///////////////////////////////////////////////////////////////////////////////
00263 // type2type
00264 //
00265 template<typename T, typename C = boost::mpl::false_>
00266 struct type2type
00267   : boost::mpl::if_<C, T const, T>
00268 {
00269 };
00270 
00271 template<typename T, typename C = boost::mpl::false_>
00272 struct foreach_iterator
00273 {
00274     typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
00275         C
00276       , range_const_iterator<T>
00277       , range_iterator<T>
00278     >::type type;
00279 };
00280 
00281 template<typename T, typename C = boost::mpl::false_>
00282 struct foreach_reference
00283   : iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
00284 {
00285 };
00286 
00287 ///////////////////////////////////////////////////////////////////////////////
00288 // encode_type
00289 //
00290 template<typename T>
00291 inline type2type<T> *encode_type(T &, boost::mpl::false_ *) { return 0; }
00292 
00293 template<typename T>
00294 inline type2type<T, const_> *encode_type(T const &, boost::mpl::true_ *) { return 0; }
00295 
00296 ///////////////////////////////////////////////////////////////////////////////
00297 // set_false
00298 //
00299 inline bool set_false(bool &b) { return b = false; }
00300 
00301 ///////////////////////////////////////////////////////////////////////////////
00302 // to_ptr
00303 //
00304 template<typename T>
00305 inline T *&to_ptr(T const &)
00306 {
00307     static T *t = 0;
00308     return t;
00309 }
00310 
00311 // Borland needs a little extra help with arrays
00312 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00313 template<typename T,std::size_t N>
00314 inline T (*to_ptr(T (&t)[N]))[N]  { return 0; }
00315 #endif
00316 
00317 ///////////////////////////////////////////////////////////////////////////////
00318 // derefof
00319 //
00320 template<typename T>
00321 inline T &derefof(T *t)
00322 {
00323     // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N],
00324     // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue.
00325     return reinterpret_cast<T &>(
00326         *const_cast<char *>(
00327             reinterpret_cast<char const volatile *>(t)
00328         )
00329     );
00330 }
00331 
00332 #ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
00333 ///////////////////////////////////////////////////////////////////////////////
00334 // Detect at compile-time whether an expression yields an rvalue or
00335 // an lvalue. This is rather non-standard, but some popular compilers
00336 // accept it.
00337 ///////////////////////////////////////////////////////////////////////////////
00338 
00339 ///////////////////////////////////////////////////////////////////////////////
00340 // rvalue_probe
00341 //
00342 template<typename T>
00343 struct rvalue_probe
00344 {
00345     // can't ever return an array by value
00346     typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<boost::is_array<T>, int, T>::type value_type;
00347     operator value_type();
00348     operator T &() const;
00349 };
00350 
00351 template<typename T>
00352 rvalue_probe<T> const make_probe(T const &t);
00353 
00354 # define BOOST_FOREACH_IS_RVALUE(COL)                                                           \
00355     boost::foreach_detail_::and_(                                                               \
00356         boost::foreach_detail_::not_(boost::foreach_detail_::is_array(COL))                     \
00357       , BOOST_FOREACH_PROTECT(boost::foreach_detail_::is_rvalue(                                \
00358             (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0)))
00359 
00360 #elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
00361 ///////////////////////////////////////////////////////////////////////////////
00362 // Detect at run-time whether an expression yields an rvalue
00363 // or an lvalue. This is 100% standard C++, but not all compilers
00364 // accept it. Also, it causes FOREACH to break when used with non-
00365 // copyable collection types.
00366 ///////////////////////////////////////////////////////////////////////////////
00367 
00368 ///////////////////////////////////////////////////////////////////////////////
00369 // rvalue_probe
00370 //
00371 template<typename T>
00372 struct rvalue_probe
00373 {
00374     rvalue_probe(T &t, bool &b)
00375       : value(t)
00376       , is_rvalue(b)
00377     {
00378     }
00379 
00380     // can't ever return an array by value
00381     typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<boost::is_array<T>, int, T>::type value_type;
00382     operator value_type()
00383     {
00384         this->is_rvalue = true;
00385         return this->value;
00386     }
00387 
00388     operator T &() const
00389     {
00390         return this->value;
00391     }
00392 
00393 private:
00394     T &value;
00395     bool &is_rvalue;
00396 };
00397 
00398 template<typename T>
00399 rvalue_probe<T> make_probe(T &t, bool &b) { return rvalue_probe<T>(t, b); }
00400 
00401 template<typename T>
00402 rvalue_probe<T const> make_probe(T const &t, bool &b)  { return rvalue_probe<T const>(t, b); }
00403 
00404 ///////////////////////////////////////////////////////////////////////////////
00405 // simple_variant
00406 //  holds either a T or a T const*
00407 template<typename T>
00408 struct simple_variant
00409 {
00410     simple_variant(T const *t)
00411       : is_rvalue(false)
00412     {
00413         *static_cast<T const **>(this->data.address()) = t;
00414     }
00415 
00416     simple_variant(T const &t)
00417       : is_rvalue(true)
00418     {
00419         ::new(this->data.address()) T(t);
00420     }
00421 
00422     simple_variant(simple_variant const &that)
00423       : is_rvalue(that.is_rvalue)
00424     {
00425         if(this->is_rvalue)
00426             ::new(this->data.address()) T(*that.get());
00427         else
00428             *static_cast<T const **>(this->data.address()) = that.get();
00429     }
00430 
00431     ~simple_variant()
00432     {
00433         if(this->is_rvalue)
00434             this->get()->~T();
00435     }
00436 
00437     T const *get() const
00438     {
00439         if(this->is_rvalue)
00440             return static_cast<T const *>(this->data.address());
00441         else
00442             return *static_cast<T const * const *>(this->data.address());
00443     }
00444 
00445 private:
00446     enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) };
00447     simple_variant &operator =(simple_variant const &);
00448     bool const is_rvalue;
00449     aligned_storage<size> data;
00450 };
00451 
00452 // If the collection is an array or is noncopyable, it must be an lvalue.
00453 // If the collection is a lightweight proxy, treat it as an rvalue
00454 // BUGBUG what about a noncopyable proxy?
00455 template<typename LValue, typename IsProxy>
00456 inline BOOST_DEDUCED_TYPENAME boost::enable_if<boost::mpl::or_<LValue, IsProxy>, IsProxy>::type *
00457 should_copy_impl(LValue *, IsProxy *, bool *)
00458 {
00459     return 0;
00460 }
00461 
00462 // Otherwise, we must determine at runtime whether it's an lvalue or rvalue
00463 inline bool *
00464 should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue)
00465 {
00466     return is_rvalue;
00467 }
00468 
00469 #endif
00470 
00471 ///////////////////////////////////////////////////////////////////////////////
00472 // contain
00473 //
00474 template<typename T>
00475 inline auto_any<T> contain(T const &t, boost::mpl::true_ *) // rvalue
00476 {
00477     return t;
00478 }
00479 
00480 template<typename T>
00481 inline auto_any<T *> contain(T &t, boost::mpl::false_ *) // lvalue
00482 {
00483     // Cannot seem to get sunpro to handle addressof() with array types.
00484     #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570))
00485     return &t;
00486     #else
00487     return boost::addressof(t);
00488     #endif
00489 }
00490 
00491 #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
00492 template<typename T>
00493 auto_any<simple_variant<T> >
00494 contain(T const &t, bool *rvalue)
00495 {
00496     return *rvalue ? simple_variant<T>(t) : simple_variant<T>(&t);
00497 }
00498 #endif
00499 
00500 /////////////////////////////////////////////////////////////////////////////
00501 // begin
00502 //
00503 template<typename T, typename C>
00504 inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
00505 begin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
00506 {
00507     return boost::begin(auto_any_cast<T, C>(col));
00508 }
00509 
00510 template<typename T, typename C>
00511 inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
00512 begin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
00513 {
00514     typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
00515     typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator;
00516     return iterator(boost::begin(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
00517 }
00518 
00519 #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
00520 template<typename T>
00521 auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>
00522 begin(auto_any_t col, type2type<T, const_> *, bool *)
00523 {
00524     return boost::begin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
00525 }
00526 #endif
00527 
00528 ///////////////////////////////////////////////////////////////////////////////
00529 // end
00530 //
00531 template<typename T, typename C>
00532 inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
00533 end(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
00534 {
00535     return boost::end(auto_any_cast<T, C>(col));
00536 }
00537 
00538 template<typename T, typename C>
00539 inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
00540 end(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
00541 {
00542     typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
00543     typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator;
00544     return iterator(boost::end(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
00545 }
00546 
00547 #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
00548 template<typename T>
00549 auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>
00550 end(auto_any_t col, type2type<T, const_> *, bool *)
00551 {
00552     return boost::end(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
00553 }
00554 #endif
00555 
00556 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
00557 template<typename T, typename C>
00558 inline auto_any<int>
00559 end(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings
00560 {
00561     return 0; // not used
00562 }
00563 #endif
00564 
00565 ///////////////////////////////////////////////////////////////////////////////
00566 // done
00567 //
00568 template<typename T, typename C>
00569 inline bool done(auto_any_t cur, auto_any_t end, type2type<T, C> *)
00570 {
00571     typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
00572     return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end);
00573 }
00574 
00575 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
00576 template<typename T, typename C>
00577 inline bool done(auto_any_t cur, auto_any_t, type2type<T *, C> *) // null-terminated C-style strings
00578 {
00579     return ! *auto_any_cast<T *, boost::mpl::false_>(cur);
00580 }
00581 #endif
00582 
00583 ///////////////////////////////////////////////////////////////////////////////
00584 // next
00585 //
00586 template<typename T, typename C>
00587 inline void next(auto_any_t cur, type2type<T, C> *)
00588 {
00589     typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
00590     ++auto_any_cast<iter_t, boost::mpl::false_>(cur);
00591 }
00592 
00593 ///////////////////////////////////////////////////////////////////////////////
00594 // deref
00595 //
00596 template<typename T, typename C>
00597 inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type
00598 deref(auto_any_t cur, type2type<T, C> *)
00599 {
00600     typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
00601     return *auto_any_cast<iter_t, boost::mpl::false_>(cur);
00602 }
00603 
00604 } // namespace foreach_detail_
00605 } // namespace boost
00606 
00607 // A sneaky way to get the type of the collection without evaluating the expression
00608 #define BOOST_FOREACH_TYPEOF(COL)                                                               \
00609     (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const(COL)))
00610 
00611 // returns true_* if the type is noncopyable
00612 #define BOOST_FOREACH_IS_NONCOPYABLE(COL)                                                       \
00613     boost_foreach_is_noncopyable(                                                               \
00614         boost::foreach_detail_::to_ptr(COL)                                                     \
00615       , boost_foreach_argument_dependent_lookup_hack_value)
00616 
00617 // returns true_* if the type is a lightweight proxy (and is not noncopyable)
00618 #define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)                                                 \
00619     boost::foreach_detail_::and_(                                                               \
00620         boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL))                         \
00621       , boost_foreach_is_lightweight_proxy(                                                     \
00622             boost::foreach_detail_::to_ptr(COL)                                                 \
00623           , boost_foreach_argument_dependent_lookup_hack_value))
00624 
00625 #ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
00626 ///////////////////////////////////////////////////////////////////////////////
00627 // R-values and const R-values supported here with zero runtime overhead
00628 ///////////////////////////////////////////////////////////////////////////////
00629 
00630 // No variable is needed to track the rvalue-ness of the collection expression
00631 # define BOOST_FOREACH_PREAMBLE()                                                               \
00632     /**/
00633 
00634 // Evaluate the collection expression
00635 # define BOOST_FOREACH_EVALUATE(COL)                                                            \
00636     (COL)
00637 
00638 # define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
00639     (true ? 0 : boost::foreach_detail_::or_(                                                    \
00640         BOOST_FOREACH_IS_RVALUE(COL)                                                            \
00641       , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
00642 
00643 #elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
00644 ///////////////////////////////////////////////////////////////////////////////
00645 // R-values and const R-values supported here
00646 ///////////////////////////////////////////////////////////////////////////////
00647 
00648 // Declare a variable to track the rvalue-ness of the collection expression
00649 # define BOOST_FOREACH_PREAMBLE()                                                               \
00650     if (bool _foreach_is_rvalue = false) {} else
00651 
00652 // Evaluate the collection expression, and detect if it is an lvalue or and rvalue
00653 # define BOOST_FOREACH_EVALUATE(COL)                                                            \
00654     (true ? boost::foreach_detail_::make_probe((COL), _foreach_is_rvalue) : (COL))
00655 
00656 // The rvalue/lvalue-ness of the collection expression is determined dynamically, unless
00657 // type type is an array or is noncopyable or is non-const, in which case we know it's an lvalue.
00658 // If the type happens to be a lightweight proxy, always make a copy.
00659 # define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
00660     (boost::foreach_detail_::should_copy_impl(                                                  \
00661         true ? 0 : boost::foreach_detail_::or_(                                                 \
00662             boost::foreach_detail_::is_array(COL)                                               \
00663           , BOOST_FOREACH_IS_NONCOPYABLE(COL)                                                   \
00664           , boost::foreach_detail_::not_(boost::foreach_detail_::is_const(COL)))                \
00665       , true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)                                      \
00666       , &_foreach_is_rvalue))
00667 
00668 #elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION)
00669 ///////////////////////////////////////////////////////////////////////////////
00670 // R-values supported here, const R-values NOT supported here
00671 ///////////////////////////////////////////////////////////////////////////////
00672 
00673 // No variable is needed to track the rvalue-ness of the collection expression
00674 # define BOOST_FOREACH_PREAMBLE()                                                               \
00675     /**/
00676 
00677 // Evaluate the collection expression
00678 # define BOOST_FOREACH_EVALUATE(COL)                                                            \
00679     (COL)
00680 
00681 // Determine whether the collection expression is an lvalue or an rvalue.
00682 // NOTE: this gets the answer wrong for const rvalues.
00683 # define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
00684     (true ? 0 : boost::foreach_detail_::or_(                                                    \
00685         boost::foreach_detail_::is_rvalue((COL), 0)                                             \
00686       , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
00687 
00688 #else
00689 ///////////////////////////////////////////////////////////////////////////////
00690 // R-values NOT supported here
00691 ///////////////////////////////////////////////////////////////////////////////
00692 
00693 // No variable is needed to track the rvalue-ness of the collection expression
00694 # define BOOST_FOREACH_PREAMBLE()                                                               \
00695     /**/
00696 
00697 // Evaluate the collection expression
00698 # define BOOST_FOREACH_EVALUATE(COL)                                                            \
00699     (COL)
00700 
00701 // Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies)
00702 # define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
00703     (true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))
00704 
00705 #endif
00706 
00707 #define BOOST_FOREACH_CONTAIN(COL)                                                              \
00708     boost::foreach_detail_::contain(                                                            \
00709         BOOST_FOREACH_EVALUATE(COL)                                                             \
00710       , BOOST_FOREACH_SHOULD_COPY(COL))
00711 
00712 #define BOOST_FOREACH_BEGIN(COL)                                                                \
00713     boost::foreach_detail_::begin(                                                              \
00714         _foreach_col                                                                            \
00715       , BOOST_FOREACH_TYPEOF(COL)                                                               \
00716       , BOOST_FOREACH_SHOULD_COPY(COL))
00717 
00718 #define BOOST_FOREACH_END(COL)                                                                  \
00719     boost::foreach_detail_::end(                                                                \
00720         _foreach_col                                                                            \
00721       , BOOST_FOREACH_TYPEOF(COL)                                                               \
00722       , BOOST_FOREACH_SHOULD_COPY(COL))
00723 
00724 #define BOOST_FOREACH_DONE(COL)                                                                 \
00725     boost::foreach_detail_::done(                                                               \
00726         _foreach_cur                                                                            \
00727       , _foreach_end                                                                            \
00728       , BOOST_FOREACH_TYPEOF(COL))
00729 
00730 #define BOOST_FOREACH_NEXT(COL)                                                                 \
00731     boost::foreach_detail_::next(                                                               \
00732         _foreach_cur                                                                            \
00733       , BOOST_FOREACH_TYPEOF(COL))
00734 
00735 #define BOOST_FOREACH_DEREF(COL)                                                                \
00736     boost::foreach_detail_::deref(                                                              \
00737         _foreach_cur                                                                            \
00738       , BOOST_FOREACH_TYPEOF(COL))
00739 
00740 ///////////////////////////////////////////////////////////////////////////////
00741 // BOOST_FOREACH
00742 //
00743 //   For iterating over collections. Collections can be
00744 //   arrays, null-terminated strings, or STL containers.
00745 //   The loop variable can be a value or reference. For
00746 //   example:
00747 //
00748 //   std::list<int> int_list(/*stuff*/);
00749 //   BOOST_FOREACH(int &i, int_list)
00750 //   {
00751 //       /*
00752 //        * loop body goes here.
00753 //        * i is a reference to the int in int_list.
00754 //        */
00755 //   }
00756 //
00757 //   Alternately, you can declare the loop variable first,
00758 //   so you can access it after the loop finishes. Obviously,
00759 //   if you do it this way, then the loop variable cannot be
00760 //   a reference.
00761 //
00762 //   int i;
00763 //   BOOST_FOREACH(i, int_list)
00764 //       { ... }
00765 //
00766 #define BOOST_FOREACH(VAR, COL)                                                                 \
00767     BOOST_FOREACH_PREAMBLE()                                                                    \
00768     if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else   \
00769     if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else     \
00770     if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else       \
00771     for (bool _foreach_continue = true;                                                         \
00772               _foreach_continue && !BOOST_FOREACH_DONE(COL);                                    \
00773               _foreach_continue ? BOOST_FOREACH_NEXT(COL) : (void)0)                            \
00774         if  (boost::foreach_detail_::set_false(_foreach_continue)) {} else                      \
00775         for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true)
00776 
00777 #ifdef foreach
00778 #undef foreach
00779 #endif
00780                                                                         #define foreach BOOST_FOREACH
00781 
00782 #endif

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs