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