├── .gitattributes ├── .travis.yml ├── CMakeLists.txt ├── build.jam ├── doc ├── Jamfile.v2 └── foreach.qbk ├── include └── boost │ ├── foreach.hpp │ └── foreach_fwd.hpp ├── index.html ├── meta └── libraries.json └── test ├── Jamfile.v2 ├── array_byref.cpp ├── array_byref_r.cpp ├── array_byval.cpp ├── array_byval_r.cpp ├── call_once.cpp ├── cstr_byref.cpp ├── cstr_byref_r.cpp ├── cstr_byval.cpp ├── cstr_byval_r.cpp ├── dependent_type.cpp ├── misc.cpp ├── noncopyable.cpp ├── pair_byref.cpp ├── pair_byref_r.cpp ├── pair_byval.cpp ├── pair_byval_r.cpp ├── rvalue_const.cpp ├── rvalue_const_r.cpp ├── rvalue_nonconst.cpp ├── rvalue_nonconst_r.cpp ├── stl_byref.cpp ├── stl_byref_r.cpp ├── stl_byval.cpp ├── stl_byval_r.cpp ├── user_defined.cpp └── utility.hpp /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol svneol=native#text/plain 2 | *.gitattributes text svneol=native#text/plain 3 | 4 | # Scriptish formats 5 | *.bat text svneol=native#text/plain 6 | *.bsh text svneol=native#text/x-beanshell 7 | *.cgi text svneol=native#text/plain 8 | *.cmd text svneol=native#text/plain 9 | *.js text svneol=native#text/javascript 10 | *.php text svneol=native#text/x-php 11 | *.pl text svneol=native#text/x-perl 12 | *.pm text svneol=native#text/x-perl 13 | *.py text svneol=native#text/x-python 14 | *.sh eol=lf svneol=LF#text/x-sh 15 | configure eol=lf svneol=LF#text/x-sh 16 | 17 | # Image formats 18 | *.bmp binary svneol=unset#image/bmp 19 | *.gif binary svneol=unset#image/gif 20 | *.ico binary svneol=unset#image/ico 21 | *.jpeg binary svneol=unset#image/jpeg 22 | *.jpg binary svneol=unset#image/jpeg 23 | *.png binary svneol=unset#image/png 24 | *.tif binary svneol=unset#image/tiff 25 | *.tiff binary svneol=unset#image/tiff 26 | *.svg text svneol=native#image/svg%2Bxml 27 | 28 | # Data formats 29 | *.pdf binary svneol=unset#application/pdf 30 | *.avi binary svneol=unset#video/avi 31 | *.doc binary svneol=unset#application/msword 32 | *.dsp text svneol=crlf#text/plain 33 | *.dsw text svneol=crlf#text/plain 34 | *.eps binary svneol=unset#application/postscript 35 | *.gz binary svneol=unset#application/gzip 36 | *.mov binary svneol=unset#video/quicktime 37 | *.mp3 binary svneol=unset#audio/mpeg 38 | *.ppt binary svneol=unset#application/vnd.ms-powerpoint 39 | *.ps binary svneol=unset#application/postscript 40 | *.psd binary svneol=unset#application/photoshop 41 | *.rdf binary svneol=unset#text/rdf 42 | *.rss text svneol=unset#text/xml 43 | *.rtf binary svneol=unset#text/rtf 44 | *.sln text svneol=native#text/plain 45 | *.swf binary svneol=unset#application/x-shockwave-flash 46 | *.tgz binary svneol=unset#application/gzip 47 | *.vcproj text svneol=native#text/xml 48 | *.vcxproj text svneol=native#text/xml 49 | *.vsprops text svneol=native#text/xml 50 | *.wav binary svneol=unset#audio/wav 51 | *.xls binary svneol=unset#application/vnd.ms-excel 52 | *.zip binary svneol=unset#application/zip 53 | 54 | # Text formats 55 | .htaccess text svneol=native#text/plain 56 | *.bbk text svneol=native#text/xml 57 | *.cmake text svneol=native#text/plain 58 | *.css text svneol=native#text/css 59 | *.dtd text svneol=native#text/xml 60 | *.htm text svneol=native#text/html 61 | *.html text svneol=native#text/html 62 | *.ini text svneol=native#text/plain 63 | *.log text svneol=native#text/plain 64 | *.mak text svneol=native#text/plain 65 | *.qbk text svneol=native#text/plain 66 | *.rst text svneol=native#text/plain 67 | *.sql text svneol=native#text/x-sql 68 | *.txt text svneol=native#text/plain 69 | *.xhtml text svneol=native#text/xhtml%2Bxml 70 | *.xml text svneol=native#text/xml 71 | *.xsd text svneol=native#text/xml 72 | *.xsl text svneol=native#text/xml 73 | *.xslt text svneol=native#text/xml 74 | *.xul text svneol=native#text/xul 75 | *.yml text svneol=native#text/plain 76 | boost-no-inspect text svneol=native#text/plain 77 | CHANGES text svneol=native#text/plain 78 | COPYING text svneol=native#text/plain 79 | INSTALL text svneol=native#text/plain 80 | Jamfile text svneol=native#text/plain 81 | Jamroot text svneol=native#text/plain 82 | Jamfile.v2 text svneol=native#text/plain 83 | Jamrules text svneol=native#text/plain 84 | Makefile* text svneol=native#text/plain 85 | README text svneol=native#text/plain 86 | TODO text svneol=native#text/plain 87 | 88 | # Code formats 89 | *.c text svneol=native#text/plain 90 | *.cpp text svneol=native#text/plain 91 | *.h text svneol=native#text/plain 92 | *.hpp text svneol=native#text/plain 93 | *.ipp text svneol=native#text/plain 94 | *.tpp text svneol=native#text/plain 95 | *.jam text svneol=native#text/plain 96 | *.java text svneol=native#text/plain 97 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2016, 2017 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | language: cpp 6 | 7 | sudo: false 8 | 9 | python: "2.7" 10 | 11 | branches: 12 | only: 13 | - master 14 | - develop 15 | - /feature\/.*/ 16 | 17 | env: 18 | matrix: 19 | - BOGUS_JOB=true 20 | 21 | matrix: 22 | 23 | exclude: 24 | - env: BOGUS_JOB=true 25 | 26 | include: 27 | - os: linux 28 | compiler: g++ 29 | env: TOOLSET=gcc CXXSTD=03,11 30 | 31 | - os: linux 32 | compiler: clang++ 33 | env: TOOLSET=clang CXXSTD=03,11,14,1z 34 | 35 | - os: osx 36 | compiler: clang++ 37 | env: TOOLSET=clang CXXSTD=03,11,14,1z 38 | 39 | install: 40 | - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true 41 | - cd .. 42 | - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root 43 | - cd boost-root 44 | - git submodule update --init tools/build 45 | - git submodule update --init libs/config 46 | - git submodule update --init tools/boostdep 47 | - cp -r $TRAVIS_BUILD_DIR/* libs/foreach 48 | - python tools/boostdep/depinst/depinst.py foreach 49 | - ./bootstrap.sh 50 | - ./b2 headers 51 | 52 | script: 53 | - ./b2 libs/foreach/test toolset=$TOOLSET cxxstd=$CXXSTD 54 | 55 | notifications: 56 | email: 57 | on_success: always 58 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake foreach` 2 | # Copyright 2020 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.5...3.16) 7 | 8 | project(boost_foreach VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | add_library(boost_foreach INTERFACE) 11 | add_library(Boost::foreach ALIAS boost_foreach) 12 | 13 | target_include_directories(boost_foreach INTERFACE include) 14 | 15 | target_link_libraries(boost_foreach 16 | INTERFACE 17 | Boost::config 18 | Boost::core 19 | Boost::iterator 20 | Boost::mpl 21 | Boost::range 22 | Boost::type_traits 23 | ) 24 | 25 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 26 | 27 | add_subdirectory(test) 28 | 29 | endif() 30 | 31 | -------------------------------------------------------------------------------- /build.jam: -------------------------------------------------------------------------------- 1 | # Copyright René Ferdinand Rivera Morell 2023-2024 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at 4 | # http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | require-b2 5.2 ; 7 | 8 | constant boost_dependencies : 9 | /boost/config//boost_config 10 | /boost/core//boost_core 11 | /boost/iterator//boost_iterator 12 | /boost/mpl//boost_mpl 13 | /boost/range//boost_range 14 | /boost/type_traits//boost_type_traits ; 15 | 16 | project /boost/foreach 17 | ; 18 | 19 | explicit 20 | [ alias boost_foreach : : : 21 | : include $(boost_dependencies) ] 22 | [ alias all : boost_foreach test ] 23 | ; 24 | 25 | call-if : boost-library foreach 26 | ; 27 | 28 | -------------------------------------------------------------------------------- /doc/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Copyright Eric Niebler 2005. Use, modification, and distribution are 2 | # subject to the Boost Software License, Version 1.0. (See accompanying 3 | # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 | 5 | using quickbook ; 6 | 7 | xml foreach : foreach.qbk ; 8 | boostbook standalone 9 | : 10 | foreach 11 | : 12 | boost.root=../../../.. 13 | pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html 14 | ; 15 | 16 | ############################################################################### 17 | alias boostdoc 18 | : foreach 19 | : 20 | : 21 | : ; 22 | explicit boostdoc ; 23 | alias boostrelease ; 24 | explicit boostrelease ; 25 | -------------------------------------------------------------------------------- /doc/foreach.qbk: -------------------------------------------------------------------------------- 1 | 2 | [library Boost.Foreach 3 | [quickbook 1.3] 4 | [authors [Niebler, Eric]] 5 | [copyright 2004 Eric Niebler] 6 | [category algorithms] 7 | [purpose 8 | foreach looping construct, for writing simple loops over STL containers, 9 | null-terminated strings, arrays, iterator pairs and user defined types. 10 | ] 11 | [id foreach] 12 | [dirname foreach] 13 | [license 14 | Distributed under the Boost Software License, Version 1.0. 15 | (See accompanying file LICENSE_1_0.txt or copy at 16 | [@http://www.boost.org/LICENSE_1_0.txt]) 17 | ] 18 | ] 19 | 20 | [/ Images ] 21 | 22 | [def _note_ [$images/note.png]] 23 | [def _alert_ [$images/caution.png]] 24 | [def _detail_ [$images/note.png]] 25 | [def _tip_ [$images/tip.png]] 26 | 27 | [/ Links ] 28 | 29 | [def _foreach_ [^BOOST_FOREACH]] 30 | [def _range_ [@../../libs/range/index.html Boost.Range]] 31 | [def _iterator_range_ [@boost:/libs/range/doc/html/range/reference/utilities/iterator_range.html `boost::iterator_range<>`]] 32 | [def _sub_range_ [@boost:/libs/range/doc/html/range/reference/utilities/sub_range.html `boost::sub_range<>`]] 33 | [def _extending_range_ [@boost:/libs/range/doc/html/range/reference/extending.html Extending Boost.Range]] 34 | [def _single_pass_range_concept_ [@boost:/libs/range/doc/html/range/concepts/single_pass_range.html Single Pass Range Concept]] 35 | [def _range_portability_ [@boost:/libs/range/doc/html/range/portability.html Boost.Range Portability]] 36 | [def _noncopyable_ [@../../libs/utility/utility.htm#Class_noncopyable `boost::noncopyable`]] 37 | [def _iterator_ [@../../libs/iterator/doc/index.html Boost.Iterator]] 38 | 39 | [section Introduction] 40 | 41 | [:["Make simple things easy.]\n[*['-- Larry Wall]]] 42 | 43 | [h2 What is _foreach_?] 44 | 45 | In C++, writing a loop that iterates over a sequence is tedious. We can either 46 | use iterators, which requires a considerable amount of boiler-plate, or we can 47 | use the `std::for_each()` algorithm and move our loop body into a predicate, which 48 | requires no less boiler-plate and forces us to move our logic far from where 49 | it will be used. In contrast, some other languages, like Perl, provide a dedicated 50 | "foreach" construct that automates this process. _foreach_ is just such a construct 51 | for C++. It iterates over sequences for us, freeing us from having to deal directly 52 | with iterators or write predicates. 53 | 54 | _foreach_ is designed for ease-of-use and efficiency. It does no dynamic allocations, 55 | makes no virtual function calls or calls through function pointers, and makes no calls 56 | that are not transparent to the compiler's optimizer. This results in near-optimal code 57 | generation; the performance of _foreach_ is usually within a few percent of the 58 | equivalent hand-coded loop. And although _foreach_ is a macro, it is a remarkably 59 | well-behaved one. It evaluates its arguments exactly once, leading to no nasty surprises. 60 | 61 | [h2 Hello, world!] 62 | 63 | Below is a sample program that uses _foreach_ to loop over the contents of 64 | a `std::string`. 65 | 66 | #include 67 | #include 68 | #include 69 | 70 | int main() 71 | { 72 | std::string hello( "Hello, world!" ); 73 | 74 | BOOST_FOREACH( char ch, hello ) 75 | { 76 | std::cout << ch; 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | This program outputs the following: 83 | 84 | [pre 85 | Hello, world! 86 | ] 87 | 88 | [h2 Supported Sequence Types] 89 | 90 | _foreach_ iterates over sequences. But what qualifies as a sequence, exactly? Since 91 | _foreach_ is built on top of _range_, it automatically supports those types which 92 | _range_ recognizes as sequences. Specifically, _foreach_ works with types that satisfy 93 | the _single_pass_range_concept_. For example, we can use _foreach_ with: 94 | 95 | * STL containers 96 | * arrays 97 | * Null-terminated strings (`char` and `wchar_t`) 98 | * std::pair of iterators 99 | 100 | [note The support for STL containers is very general; anything that looks like 101 | an STL container counts. If it has nested `iterator` and `const_iterator` types and `begin()` 102 | and `end()` member functions, _foreach_ will automatically know how to iterate over 103 | it. It is in this way that _iterator_range_ and _sub_range_ work with _foreach_.] 104 | 105 | See the section on [link foreach.extensibility Extensibility] to find 106 | out how to make _foreach_ work with other types. 107 | 108 | [h2 Examples] 109 | 110 | Below are some examples that demonstrate all the different ways we can use _foreach_. 111 | 112 | Iterate over an STL container: 113 | 114 | std::list list_int( /*...*/ ); 115 | BOOST_FOREACH( int i, list_int ) 116 | { 117 | // do something with i 118 | } 119 | 120 | Iterate over an array, with covariance (i.e., the type of the iteration variable is 121 | not exactly the same as the element type of the container): 122 | 123 | short array_short[] = {1,2,3}; 124 | BOOST_FOREACH( int i, array_short ) 125 | { 126 | // The short was implicitly converted to an int 127 | } 128 | 129 | Predeclare the loop variable, and use `break`, `continue`, and `return` in the loop body: 130 | 131 | std::deque deque_int( /*...*/ ); 132 | int i = 0; 133 | BOOST_FOREACH( i, deque_int ) 134 | { 135 | if( i == 0 ) return; 136 | if( i == 1 ) continue; 137 | if( i == 2 ) break; 138 | } 139 | 140 | Iterate over a sequence by reference, and modify the underlying sequence: 141 | 142 | short array_short[] = { 1, 2, 3 }; 143 | BOOST_FOREACH( short & i, array_short ) 144 | { 145 | ++i; 146 | } 147 | // array_short contains {2,3,4} here 148 | 149 | Iterate over a vector of vectors with nested _foreach_ loops. In this 150 | example, notice that braces around the loop body are not necessary: 151 | 152 | std::vector > matrix_int; 153 | BOOST_FOREACH( std::vector & row, matrix_int ) 154 | BOOST_FOREACH( int & i, row ) 155 | ++i; 156 | 157 | Iterate over an expression that returns a sequence by value (i.e. an rvalue): 158 | 159 | extern std::vector get_vector_float(); 160 | BOOST_FOREACH( float f, get_vector_float() ) 161 | { 162 | // Note: get_vector_float() will be called exactly once 163 | } 164 | 165 | Iterate in reverse: 166 | 167 | std::list list_int( /*...*/ ); 168 | BOOST_REVERSE_FOREACH( int i, list_int ) 169 | { 170 | // do something with i 171 | } 172 | 173 | Iterating over rvalues doesn't work on some older compilers. Check the 174 | [link foreach.portability Portability] section to see whether your 175 | compiler supports this. 176 | 177 | [h2 Making _foreach_ Prettier] 178 | 179 | People have complained about the name _foreach_. It's too long. `ALL CAPS` can 180 | get tiresome to look at. That may be true, but _foreach_ is merely following 181 | the [@http://www.boost.org/more/lib_guide.htm Boost Naming Convention]. That 182 | doesn't mean you're stuck with it, though. If you would like to use a different 183 | identifier (`foreach_`, perhaps), you can simply do: 184 | 185 | #define foreach_ BOOST_FOREACH 186 | #define foreach_r_ BOOST_REVERSE_FOREACH 187 | 188 | Only do this if you are sure that the identifier you choose will not cause 189 | name conflicts in your code. 190 | 191 | [note Do not use `#define foreach_(x,y) BOOST_FOREACH(x,y)`. 192 | This can be problematic if the arguments are macros themselves. This would 193 | result in an additional expansion of these macros. Instead, use the 194 | form shown above.] 195 | 196 | Lastly, a word of warning. Lots of folks use a `foreach` macro as a short form 197 | for `BOOST_FOREACH`. I discourage this. It leads to name conflicts within the 198 | `BOOST_FOREACH` macro itself, where `foreach` is the name of a namespace. Besides, 199 | `foreach` is a common-enough identifier; even [@http://qt.digia.com/ Qt] defines 200 | it as a macro. If you insist on using `foreach`, you might try something like this: 201 | 202 | #include 203 | 204 | namespace boost 205 | { 206 | // Suggested work-around for https://svn.boost.org/trac/boost/ticket/6131 207 | namespace BOOST_FOREACH = foreach; 208 | } 209 | 210 | #define foreach BOOST_FOREACH 211 | 212 | This will work around /some/ of the problems you're likely to encounter, but not all. 213 | Prefer using a different identifier. 214 | 215 | [endsect] 216 | 217 | [section Extensibility] 218 | 219 | If we want to use _foreach_ to iterate over some new collection type, we must 220 | "teach" _foreach_ how to interact with our type. Since _foreach_ is built on top 221 | of _range_, we must extend _range_ in order to extend _foreach_. The section 222 | _extending_range_ explores this topic in detail. 223 | 224 | Below is an example for extending _foreach_ to iterate over a sub-string type, 225 | which contains two iterators into a `std::string`. 226 | 227 | namespace my 228 | { 229 | // sub_string: part of a string, as delimited by a pair 230 | // of iterators 231 | struct sub_string 232 | { 233 | std::string::iterator begin; 234 | std::string::iterator end; 235 | 236 | /* ... implementation ... */ 237 | }; 238 | 239 | // Add overloads of range_begin() and range_end() in the 240 | // same namespace as sub_string, to be found by Argument-Dependent Lookup. 241 | 242 | inline std::string::iterator range_begin( sub_string & x ) 243 | { 244 | return x.begin; 245 | } 246 | 247 | inline std::string::iterator range_end( sub_string & x ) 248 | { 249 | return x.end; 250 | } 251 | 252 | // Also add overloads for const sub_strings. Note we use the conversion 253 | // from string::iterator to string::const_iterator here. 254 | 255 | inline std::string::const_iterator range_begin( sub_string const & x ) 256 | { 257 | return x.begin; 258 | } 259 | 260 | inline std::string::const_iterator range_end( sub_string const & x ) 261 | { 262 | return x.end; 263 | } 264 | } 265 | 266 | namespace boost 267 | { 268 | // specialize range_mutable_iterator and range_const_iterator in namespace boost 269 | template<> 270 | struct range_mutable_iterator< my::sub_string > 271 | { 272 | typedef std::string::iterator type; 273 | }; 274 | 275 | template<> 276 | struct range_const_iterator< my::sub_string > 277 | { 278 | typedef std::string::const_iterator type; 279 | }; 280 | } 281 | 282 | Now that we have taught _range_ (and hence _foreach_) about our type, we 283 | can now use _foreach_ to iterate over our sub_string type. 284 | 285 | my::sub_string substr; 286 | BOOST_FOREACH( char ch, substr ) 287 | { 288 | // Woo-hoo! 289 | } 290 | 291 | There are some portability issues we should be aware of when extending _foreach_. Be sure 292 | to check out the [link foreach.portability Portability] section. In particular, if your 293 | compiler does not support Argument-Dependent Lookup, the _range_portability_ section 294 | offers some suggested work-arounds. 295 | 296 | [h2 Making _foreach_ Work with Non-Copyable Sequence Types] 297 | 298 | For sequence types that are non-copyable, we will need to tell _foreach_ to 299 | not try to make copies. If our type inherits from _noncopyable_, no further action is 300 | required. If not, we must specialize the `boost::foreach::is_noncopyable<>` template, as 301 | follows: 302 | 303 | class noncopy_vector 304 | { 305 | // ... 306 | private: 307 | noncopy_vector( noncopy_vector const & ); // non-copyable! 308 | }; 309 | 310 | namespace boost { namespace foreach 311 | { 312 | template<> 313 | struct is_noncopyable< noncopy_vector > 314 | : mpl::true_ 315 | { 316 | }; 317 | }} 318 | 319 | Another way to achieve the same effect is to override the global `boost_foreach_is_noncopyable()` 320 | function. Doing it this way has the advantage of being portable to older compilers. 321 | 322 | // At global scope... 323 | inline boost::mpl::true_ * 324 | boost_foreach_is_noncopyable( noncopy_vector *&, boost::foreach::tag ) 325 | { 326 | return 0; 327 | } 328 | 329 | [tip Even though we have to tell _foreach_ that our type is non-copyable, that 330 | doesn't mean that _foreach_ always makes a copy of our sequence type. Obviously, doing so 331 | would be expensive and even wrong in some cases. _foreach_ is quite smart about when to 332 | make a copy and when not to. The `is_noncopyable<>` trait is needed to elide the copy, which 333 | is on a branch that might never get taken.] 334 | 335 | [h2 Optimizing _foreach_ for Lightweight Proxy Sequence Types] 336 | 337 | On some compilers, _foreach_ must occasionally take a slightly slower code path to guarantee 338 | correct handling of sequences stored in temporary objects. It asks itself, "Should I make 339 | a copy of this object?" and later, "Did I make a copy or not?" For some types of sequences, 340 | this is overkill. Consider a sequence which is a simple pair of iterators. Jumping through 341 | hoops of fire to avoid copying it doesn't make sense because copying it is so cheap. 342 | 343 | A pair of iterators is an example of a lightweight proxy. It does not store the values of 344 | the sequence; rather, it stores iterators to them. This means that iterating over a copy of 345 | the proxy object will give the same results as using the object itself. For such types, 346 | _foreach_ provides a hook that lets us tell it not to worry about the expense of making a 347 | copy. This can result in slightly faster loop execution. Simply specialize the 348 | `boost::foreach::is_lightweight_proxy<>` trait, as follows: 349 | 350 | struct sub_string 351 | : boost::iterator_range< std::string::iterator > 352 | { 353 | // ... 354 | }; 355 | 356 | namespace boost { namespace foreach 357 | { 358 | template<> 359 | struct is_lightweight_proxy< sub_string > 360 | : mpl::true_ 361 | { 362 | }; 363 | }} 364 | 365 | Alternately, we could achieve the same effect by overriding the global 366 | `boost_foreach_is_lightweight_proxy()` function, as follows: 367 | 368 | // At global scope... 369 | inline boost::mpl::true_ * 370 | boost_foreach_is_lightweight_proxy( sub_string *&, boost::foreach::tag ) 371 | { 372 | return 0; 373 | } 374 | 375 | This method is portable to older compilers. 376 | 377 | [endsect] 378 | 379 | [section Portability] 380 | 381 | _foreach_ uses some fairly sophisticated techniques that not all compilers support. Depending 382 | on how compliant your compiler is, you may not be able to use _foreach_ in some scenarios. Since 383 | _foreach_ uses _range_, it inherits _range_'s portability issues. You can read about those 384 | issues in the _range_portability_ section. 385 | 386 | In addition to the demands placed on the compiler by _range_, _foreach_ places additional demands 387 | in order to handle rvalue sequences properly. (Recall that an rvalue is an unnamed object, so 388 | an example of an rvalue sequence would be a function that returns a `std::vector<>` by value.) Compilers 389 | vary in their handling of rvalues and lvalues. To cope with the situation _foreach_ defines three 390 | levels of compliance, described below: 391 | 392 | [table BOOST_FOREACH Compliance Levels 393 | [[Level] [Meaning]] 394 | [[*Level 0*] [['[_Highest level of compliance]]\n 395 | _foreach_ works with lvalues, rvalues and const-qualified rvalues.]] 396 | [[*Level 1*] [['[_Moderate level of compliance]]\n 397 | _foreach_ works with lvalues and plain rvalues, but not const-qualified rvalues.\n 398 | `BOOST_FOREACH_NO_CONST_RVALUE_DETECTION` is defined in this case.]] 399 | [[*Level 2*] [['[_Lowest level of compliance]]\n 400 | _foreach_ works with lvalues only, not rvalues.\n 401 | `BOOST_FOREACH_NO_RVALUE_DETECTION` is defined in this case.]] 402 | ] 403 | 404 | Below are the compilers with which _foreach_ has been tested, and the compliance level _foreach_ 405 | provides for them. 406 | 407 | [table Compiler Compliance Level 408 | [[Compiler] [Compliance Level]] 409 | [[Visual C++ 8.0] [Level 0]] 410 | [[Visual C++ 7.1] [Level 0]] 411 | [[Visual C++ 7.0] [Level 2]] 412 | [[Visual C++ 6.0] [Level 2]] 413 | [[gcc 4.0] [Level 0]] 414 | [[gcc 3.4] [Level 0]] 415 | [[gcc 3.3] [Level 0]] 416 | [[mingw 3.4] [Level 0]] 417 | [[Intel for Linux 9.0] [Level 0]] 418 | [[Intel for Windows 9.0] [Level 0]] 419 | [[Intel for Windows 8.0] [Level 1]] 420 | [[Intel for Windows 7.0] [Level 2]] 421 | [[Comeau 4.3.3] [Level 0]] 422 | [[Borland 5.6.4] [Level 2]] 423 | [[Metrowerks 9.5] [Level 1]] 424 | [[Metrowerks 9.4] [Level 1]] 425 | [[SunPro 5.8] [Level 2]] 426 | [[qcc 3.3] [Level 0]] 427 | [[tru64cxx 65] [Level 2]] 428 | [[tru64cxx 71] [Level 2]] 429 | ] 430 | 431 | [endsect] 432 | 433 | [section Pitfalls] 434 | 435 | This section describes some common pitfalls with _foreach_. 436 | 437 | [h2 Types With Commas] 438 | 439 | Since _foreach_ is a macro, it must have exactly two arguments, with exactly one 440 | comma separating them. That's not always convenient, especially when the type of the 441 | loop variable is a template. Consider trying to iterate over a `std::map`: 442 | 443 | std::map m; 444 | 445 | // ERROR! Too many arguments to BOOST_FOREACH macro. 446 | BOOST_FOREACH(std::pair p, m) // ... 447 | 448 | One way to fix this is with a typedef. 449 | 450 | std::map m; 451 | typedef std::pair pair_t; 452 | 453 | BOOST_FOREACH(pair_t p, m) // ... 454 | 455 | Another way to fix it is to predeclare the loop variable: 456 | 457 | std::map m; 458 | std::pair p; 459 | 460 | BOOST_FOREACH(p, m) // ... 461 | 462 | [h2 Hoisting and Iterator Invalidation] 463 | 464 | Under the covers, _foreach_ uses iterators to traverse the element 465 | sequence. Before the loop is executed, the end iterator is cached 466 | in a local variable. This is called ['hoisting], and it is an 467 | important optimization. It assumes, however, that the end iterator 468 | of the sequence is stable. It usually is, but if we modify the 469 | sequence by adding or removing elements while we are iterating 470 | over it, we may end up hoisting ourselves on our own petard. 471 | 472 | Consider the following code: 473 | 474 | std::vector vect(4, 4); 475 | BOOST_FOREACH(int i, vect) 476 | { 477 | vect.push_back(i + 1); 478 | } 479 | 480 | This code will compile, but it has undefined behavior. That is because 481 | it is logically equivalent to the following: 482 | 483 | std::vector vect(4, 4); 484 | for(std::vector::iterator it1 = vect.begin(), it2 = vect.end(); 485 | it1 != it2; ++it1) 486 | { 487 | int i = *it1; 488 | vect.push_back(i + 1); // Oops! This invalidates it1 and it2! 489 | } 490 | 491 | The call to `vect.push_back()` will cause all iterators into `vect` to 492 | become invalid, including `it1` and `it2`. The next iteration through 493 | the loop will cause the invalid iterators to be used. That's bad news. 494 | 495 | The moral of the story is to think twice before adding and removing 496 | elements from the sequence over which you are iterating. If doing 497 | so could cause iterators to become invalid, don't do it. Use a regular 498 | `for` loop instead. 499 | 500 | [endsect] 501 | 502 | [section History and Acknowledgements] 503 | 504 | [h2 History] 505 | 506 | The ideas for _foreach_ began life in the Visual C++ group at Microsoft during the early phases of 507 | the design for C++\/CLI. Whether to add a dedicated "foreach" looping construct to the language was 508 | an open question at the time. As a mental exercise, Anson Tsao sent around some proof-of-concept 509 | code which demonstrated that a pure library solution might be possible. The code was written in the 510 | proposed C++\/CLI dialect of the time, for which there was no compiler as of yet. I was intrigued by 511 | the possibility, and I ported his code to Managed C++ and got it working. We worked together to 512 | refine the idea and eventually published an article about it in the November 2003 issue of the 513 | CUJ. 514 | 515 | After leaving Microsoft, I revisited the idea of a looping construct. I reimplemented the macro 516 | from scratch in standard C++, corrected some shortcomings of the CUJ version and rechristened it 517 | _foreach_. In October of 2003 I began a discussion about it on the Boost developers list, where 518 | it met with a luke-warm reception. I dropped the issue until December 2004, when I reimplemented 519 | _foreach_ yet again. The new version only evaluated its sequence expression once and correctly 520 | handled both lvalue and rvalue sequence expressions. It was built on top of the recently 521 | accepted _range_ library, which increased its portability. This was the version that, on Dec. 12 2004, 522 | I finally submitted to Boost for review. It was accepted into Boost on May 5, 2005. 523 | 524 | [h2 Acknowledgements] 525 | 526 | Thanks go out to Anson Tsao of Microsoft for coming up with the idea and demonstrating its feasibility. 527 | I would also like to thank [@http://boost.org/people/thorsten_ottosen.html Thorsten Ottosen] for 528 | the _range_ library, on which the current version of _foreach_ is built. Finally, I'd like to thank 529 | Russell Hind, Alisdair Meredith and Stefan Slapeta for their help porting to various compilers. 530 | 531 | [h2 Further Reading] 532 | 533 | For more information about how _foreach_ works, you may refer to the article 534 | [@http://www.artima.com/cppsource/foreach.html ["Conditional Love]] at 535 | [@http://www.artima.com/cppsource/ The C++ Source]. 536 | 537 | [endsect] 538 | -------------------------------------------------------------------------------- /include/boost/foreach.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // foreach.hpp header file 3 | // 4 | // Copyright 2004 Eric Niebler. 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // See http://www.boost.org/libs/foreach for documentation 9 | // 10 | // Credits: 11 | // Anson Tsao - for the initial inspiration and several good suggestions. 12 | // Thorsten Ottosen - for Boost.Range, and for suggesting a way to detect 13 | // const-qualified rvalues at compile time on VC7.1+ 14 | // Russell Hind - For help porting to Borland 15 | // Alisdair Meredith - For help porting to Borland 16 | // Stefan Slapeta - For help porting to Intel 17 | // David Jenkins - For help finding a Microsoft Code Analysis bug 18 | // mimomorin@... - For a patch to use rvalue refs on supporting compilers 19 | 20 | #ifndef BOOST_FOREACH 21 | 22 | // MS compatible compilers support #pragma once 23 | #if defined(_MSC_VER) 24 | # pragma once 25 | #endif 26 | 27 | #include 28 | #include // for std::pair 29 | 30 | #include 31 | #include 32 | 33 | // Define a compiler generic null pointer value 34 | #if defined(BOOST_NO_NULLPTR) 35 | #define BOOST_FOREACH_NULL 0 36 | #else 37 | #define BOOST_FOREACH_NULL nullptr 38 | #endif 39 | 40 | // Some compilers let us detect even const-qualified rvalues at compile-time 41 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ 42 | || defined(BOOST_MSVC) && !defined(_PREFAST_) \ 43 | || (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) && \ 44 | !defined(BOOST_CLANG)) \ 45 | || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL) && \ 46 | !defined(BOOST_CLANG)) 47 | # define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION 48 | #else 49 | // Some compilers allow temporaries to be bound to non-const references. 50 | // These compilers make it impossible to for BOOST_FOREACH to detect 51 | // temporaries and avoid reevaluation of the collection expression. 52 | # if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x593) \ 53 | || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \ 54 | || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) \ 55 | || BOOST_WORKAROUND(__DECCXX_VER, <= 60590042) 56 | # define BOOST_FOREACH_NO_RVALUE_DETECTION 57 | # endif 58 | // Some compilers do not correctly implement the lvalue/rvalue conversion 59 | // rules of the ternary conditional operator. 60 | # if defined(BOOST_FOREACH_NO_RVALUE_DETECTION) \ 61 | || defined(BOOST_NO_SFINAE) \ 62 | || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ 63 | || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(1400)) \ 64 | || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__)) \ 65 | || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) \ 66 | || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) \ 67 | || BOOST_WORKAROUND(__SUNPRO_CC, >= 0x5100) \ 68 | || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x590)) 69 | # define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION 70 | # else 71 | # define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 72 | # endif 73 | #endif 74 | 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include 81 | #include 82 | #include 83 | #include 84 | #include 85 | #include 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | #include 95 | 96 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 97 | # include 98 | # include 99 | # include 100 | # include 101 | #endif 102 | 103 | namespace boost 104 | { 105 | 106 | // forward declarations for iterator_range 107 | template 108 | class iterator_range; 109 | 110 | // forward declarations for sub_range 111 | template 112 | class sub_range; 113 | 114 | namespace foreach 115 | { 116 | /////////////////////////////////////////////////////////////////////////////// 117 | // in_range 118 | // 119 | template 120 | inline std::pair in_range(T begin, T end) 121 | { 122 | return std::make_pair(begin, end); 123 | } 124 | 125 | /////////////////////////////////////////////////////////////////////////////// 126 | // boost::foreach::is_lightweight_proxy 127 | // Specialize this for user-defined collection types if they are inexpensive to copy. 128 | // This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff. 129 | template 130 | struct is_lightweight_proxy 131 | : boost::mpl::false_ 132 | { 133 | }; 134 | 135 | /////////////////////////////////////////////////////////////////////////////// 136 | // boost::foreach::is_noncopyable 137 | // Specialize this for user-defined collection types if they cannot be copied. 138 | // This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff. 139 | template 140 | struct is_noncopyable 141 | #if !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) && !defined(BOOST_NO_IS_ABSTRACT) 142 | : boost::mpl::or_< 143 | boost::is_abstract 144 | , boost::is_base_and_derived 145 | > 146 | #elif !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) 147 | : boost::is_base_and_derived 148 | #elif !defined(BOOST_NO_IS_ABSTRACT) 149 | : boost::is_abstract 150 | #else 151 | : boost::mpl::false_ 152 | #endif 153 | { 154 | }; 155 | 156 | } // namespace foreach 157 | 158 | } // namespace boost 159 | 160 | // vc6/7 needs help ordering the following overloads 161 | #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 162 | # define BOOST_FOREACH_TAG_DEFAULT ... 163 | #else 164 | # define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag 165 | #endif 166 | 167 | /////////////////////////////////////////////////////////////////////////////// 168 | // boost_foreach_is_lightweight_proxy 169 | // Another customization point for the is_lightweight_proxy optimization, 170 | // this one works on legacy compilers. Overload boost_foreach_is_lightweight_proxy 171 | // at the global namespace for your type. 172 | template 173 | inline boost::foreach::is_lightweight_proxy * 174 | boost_foreach_is_lightweight_proxy(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } 175 | 176 | template 177 | inline boost::mpl::true_ * 178 | boost_foreach_is_lightweight_proxy(std::pair *&, boost::foreach::tag) { return 0; } 179 | 180 | template 181 | inline boost::mpl::true_ * 182 | boost_foreach_is_lightweight_proxy(boost::iterator_range *&, boost::foreach::tag) { return 0; } 183 | 184 | template 185 | inline boost::mpl::true_ * 186 | boost_foreach_is_lightweight_proxy(boost::sub_range *&, boost::foreach::tag) { return 0; } 187 | 188 | template 189 | inline boost::mpl::true_ * 190 | boost_foreach_is_lightweight_proxy(T **&, boost::foreach::tag) { return 0; } 191 | 192 | /////////////////////////////////////////////////////////////////////////////// 193 | // boost_foreach_is_noncopyable 194 | // Another customization point for the is_noncopyable trait, 195 | // this one works on legacy compilers. Overload boost_foreach_is_noncopyable 196 | // at the global namespace for your type. 197 | template 198 | inline boost::foreach::is_noncopyable * 199 | boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } 200 | 201 | namespace boost 202 | { 203 | 204 | namespace foreach_detail_ 205 | { 206 | 207 | /////////////////////////////////////////////////////////////////////////////// 208 | // Define some utilities for assessing the properties of expressions 209 | // 210 | template 211 | inline boost::mpl::and_ *and_(Bool1 *, Bool2 *) { return 0; } 212 | 213 | template 214 | inline boost::mpl::and_ *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; } 215 | 216 | template 217 | inline boost::mpl::or_ *or_(Bool1 *, Bool2 *) { return 0; } 218 | 219 | template 220 | inline boost::mpl::or_ *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; } 221 | 222 | template 223 | inline boost::mpl::not_ *not_(Bool1 *) { return 0; } 224 | 225 | template 226 | inline boost::is_array *is_array_(T const &) { return 0; } 227 | 228 | template 229 | inline boost::is_const *is_const_(T &) { return 0; } 230 | 231 | #ifndef BOOST_FOREACH_NO_RVALUE_DETECTION 232 | template 233 | inline boost::mpl::true_ *is_const_(T const &) { return 0; } 234 | #endif 235 | 236 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES 237 | template 238 | inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; } 239 | 240 | template 241 | inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; } 242 | #else 243 | template 244 | inline boost::is_rvalue_reference *is_rvalue_(T &&, int) { return 0; } 245 | #endif 246 | 247 | /////////////////////////////////////////////////////////////////////////////// 248 | // auto_any_t/auto_any 249 | // General utility for putting an object of any type into automatic storage 250 | struct auto_any_base 251 | { 252 | // auto_any_base must evaluate to false in boolean context so that 253 | // they can be declared in if() statements. 254 | operator bool() const 255 | { 256 | return false; 257 | } 258 | }; 259 | 260 | template 261 | struct auto_any : auto_any_base 262 | { 263 | explicit auto_any(T const &t) 264 | : item(t) 265 | { 266 | } 267 | 268 | // temporaries of type auto_any will be bound to const auto_any_base 269 | // references, but we still want to be able to mutate the stored 270 | // data, so declare it as mutable. 271 | mutable T item; 272 | }; 273 | 274 | typedef auto_any_base const &auto_any_t; 275 | 276 | template 277 | inline BOOST_DEDUCED_TYPENAME boost::mpl::if_::type &auto_any_cast(auto_any_t a) 278 | { 279 | return static_cast const &>(a).item; 280 | } 281 | 282 | typedef boost::mpl::true_ const_; 283 | 284 | /////////////////////////////////////////////////////////////////////////////// 285 | // type2type 286 | // 287 | template 288 | struct type2type 289 | : boost::mpl::if_ 290 | { 291 | }; 292 | 293 | template 294 | struct wrap_cstr 295 | { 296 | typedef T type; 297 | }; 298 | 299 | template<> 300 | struct wrap_cstr 301 | { 302 | typedef wrap_cstr type; 303 | typedef char *iterator; 304 | typedef char *const_iterator; 305 | }; 306 | 307 | template<> 308 | struct wrap_cstr 309 | { 310 | typedef wrap_cstr type; 311 | typedef char const *iterator; 312 | typedef char const *const_iterator; 313 | }; 314 | 315 | template<> 316 | struct wrap_cstr 317 | { 318 | typedef wrap_cstr type; 319 | typedef wchar_t *iterator; 320 | typedef wchar_t *const_iterator; 321 | }; 322 | 323 | template<> 324 | struct wrap_cstr 325 | { 326 | typedef wrap_cstr type; 327 | typedef wchar_t const *iterator; 328 | typedef wchar_t const *const_iterator; 329 | }; 330 | 331 | template 332 | struct is_char_array 333 | : mpl::and_< 334 | is_array 335 | , mpl::or_< 336 | is_convertible 337 | , is_convertible 338 | > 339 | > 340 | {}; 341 | 342 | template 343 | struct foreach_iterator 344 | { 345 | // **** READ THIS IF YOUR COMPILE BREAKS HERE **** 346 | // 347 | // There is an ambiguity about how to iterate over arrays of char and wchar_t. 348 | // Should the last array element be treated as a null terminator to be skipped, or 349 | // is it just like any other element in the array? To fix the problem, you must 350 | // say which behavior you want. 351 | // 352 | // To treat the container as a null-terminated string, merely cast it to a 353 | // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... 354 | // 355 | // To treat the container as an array, use boost::as_array() in , 356 | // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... 357 | BOOST_MPL_ASSERT_MSG( (!is_char_array::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); 358 | 359 | // If the type is a pointer to a null terminated string (as opposed 360 | // to an array type), there is no ambiguity. 361 | typedef BOOST_DEDUCED_TYPENAME wrap_cstr::type container; 362 | 363 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< 364 | C 365 | , range_const_iterator 366 | , range_mutable_iterator 367 | >::type type; 368 | }; 369 | 370 | 371 | template 372 | struct foreach_reverse_iterator 373 | { 374 | // **** READ THIS IF YOUR COMPILE BREAKS HERE **** 375 | // 376 | // There is an ambiguity about how to iterate over arrays of char and wchar_t. 377 | // Should the last array element be treated as a null terminator to be skipped, or 378 | // is it just like any other element in the array? To fix the problem, you must 379 | // say which behavior you want. 380 | // 381 | // To treat the container as a null-terminated string, merely cast it to a 382 | // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... 383 | // 384 | // To treat the container as an array, use boost::as_array() in , 385 | // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... 386 | BOOST_MPL_ASSERT_MSG( (!is_char_array::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); 387 | 388 | // If the type is a pointer to a null terminated string (as opposed 389 | // to an array type), there is no ambiguity. 390 | typedef BOOST_DEDUCED_TYPENAME wrap_cstr::type container; 391 | 392 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< 393 | C 394 | , range_reverse_iterator 395 | , range_reverse_iterator 396 | >::type type; 397 | }; 398 | 399 | template 400 | struct foreach_reference 401 | : iterator_reference::type> 402 | { 403 | }; 404 | 405 | /////////////////////////////////////////////////////////////////////////////// 406 | // encode_type 407 | // 408 | template 409 | inline type2type *encode_type(T &, boost::false_type*) { return 0; } 410 | 411 | template 412 | inline type2type *encode_type(T const &, boost::true_type*) { return 0; } 413 | 414 | template 415 | inline type2type *encode_type(T &, boost::mpl::false_*) { return 0; } 416 | 417 | template 418 | inline type2type *encode_type(T const &, boost::mpl::true_*) { return 0; } 419 | 420 | /////////////////////////////////////////////////////////////////////////////// 421 | // set_false 422 | // 423 | inline bool set_false(bool &b) 424 | { 425 | b = false; 426 | return false; 427 | } 428 | 429 | /////////////////////////////////////////////////////////////////////////////// 430 | // to_ptr 431 | // 432 | template 433 | inline T *&to_ptr(T const &) 434 | { 435 | static T *t = 0; 436 | return t; 437 | } 438 | 439 | // Borland needs a little extra help with arrays 440 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 441 | template 442 | inline T (*&to_ptr(T (&)[N]))[N] 443 | { 444 | static T (*t)[N] = 0; 445 | return t; 446 | } 447 | 448 | /////////////////////////////////////////////////////////////////////////////// 449 | // derefof 450 | // 451 | template 452 | inline T &derefof(T *t) 453 | { 454 | // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N], 455 | // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue. 456 | return reinterpret_cast( 457 | *const_cast( 458 | reinterpret_cast(t) 459 | ) 460 | ); 461 | } 462 | 463 | # define BOOST_FOREACH_DEREFOF(T) boost::foreach_detail_::derefof(*T) 464 | #else 465 | # define BOOST_FOREACH_DEREFOF(T) (*T) 466 | #endif 467 | 468 | #if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ 469 | && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 470 | /////////////////////////////////////////////////////////////////////////////// 471 | // Rvalue references makes it drop-dead simple to detect at compile time 472 | // whether an expression is an rvalue. 473 | /////////////////////////////////////////////////////////////////////////////// 474 | 475 | # define BOOST_FOREACH_IS_RVALUE(COL) \ 476 | boost::foreach_detail_::is_rvalue_((COL), 0) 477 | 478 | #elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ 479 | && defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 480 | /////////////////////////////////////////////////////////////////////////////// 481 | // Detect at compile-time whether an expression yields an rvalue or 482 | // an lvalue. This is rather non-standard, but some popular compilers 483 | // accept it. 484 | /////////////////////////////////////////////////////////////////////////////// 485 | 486 | /////////////////////////////////////////////////////////////////////////////// 487 | // rvalue_probe 488 | // 489 | template 490 | struct rvalue_probe 491 | { 492 | struct private_type_ {}; 493 | // can't ever return an array by value 494 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< 495 | boost::mpl::or_, boost::is_array >, private_type_, T 496 | >::type value_type; 497 | operator value_type() { return *reinterpret_cast(this); } // never called 498 | operator T &() const { return *reinterpret_cast(const_cast(this)); } // never called 499 | }; 500 | 501 | template 502 | rvalue_probe const make_probe(T const &) 503 | { 504 | return rvalue_probe(); 505 | } 506 | 507 | # define BOOST_FOREACH_IS_RVALUE(COL) \ 508 | boost::foreach_detail_::and_( \ 509 | boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL)) \ 510 | , (true ? 0 : boost::foreach_detail_::is_rvalue_( \ 511 | (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0))) 512 | 513 | #elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) 514 | /////////////////////////////////////////////////////////////////////////////// 515 | // Detect at run-time whether an expression yields an rvalue 516 | // or an lvalue. This is 100% standard C++, but not all compilers 517 | // accept it. Also, it causes FOREACH to break when used with non- 518 | // copyable collection types. 519 | /////////////////////////////////////////////////////////////////////////////// 520 | 521 | /////////////////////////////////////////////////////////////////////////////// 522 | // rvalue_probe 523 | // 524 | template 525 | struct rvalue_probe 526 | { 527 | rvalue_probe(T &t, bool &b) 528 | : value(t) 529 | , is_rvalue(b) 530 | { 531 | } 532 | 533 | struct private_type_ {}; 534 | // can't ever return an array or an abstract type by value 535 | #ifdef BOOST_NO_IS_ABSTRACT 536 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< 537 | boost::is_array, private_type_, T 538 | >::type value_type; 539 | #else 540 | typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< 541 | boost::mpl::or_, boost::is_array >, private_type_, T 542 | >::type value_type; 543 | #endif 544 | 545 | operator value_type() 546 | { 547 | this->is_rvalue = true; 548 | return this->value; 549 | } 550 | 551 | operator T &() const 552 | { 553 | return this->value; 554 | } 555 | 556 | private: 557 | T &value; 558 | bool &is_rvalue; 559 | }; 560 | 561 | template 562 | rvalue_probe make_probe(T &t, bool &b) { return rvalue_probe(t, b); } 563 | 564 | template 565 | rvalue_probe make_probe(T const &t, bool &b) { return rvalue_probe(t, b); } 566 | 567 | /////////////////////////////////////////////////////////////////////////////// 568 | // simple_variant 569 | // holds either a T or a T const* 570 | template 571 | struct simple_variant 572 | { 573 | simple_variant(T const *t) 574 | : is_rvalue(false) 575 | { 576 | *static_cast(this->data.address()) = t; 577 | } 578 | 579 | simple_variant(T const &t) 580 | : is_rvalue(true) 581 | { 582 | ::new(this->data.address()) T(t); 583 | } 584 | 585 | simple_variant(simple_variant const &that) 586 | : is_rvalue(that.is_rvalue) 587 | { 588 | if(this->is_rvalue) 589 | ::new(this->data.address()) T(*that.get()); 590 | else 591 | *static_cast(this->data.address()) = that.get(); 592 | } 593 | 594 | ~simple_variant() 595 | { 596 | if(this->is_rvalue) 597 | this->get()->~T(); 598 | } 599 | 600 | T const *get() const 601 | { 602 | if(this->is_rvalue) 603 | return static_cast(this->data.address()); 604 | else 605 | return *static_cast(this->data.address()); 606 | } 607 | 608 | private: 609 | enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) }; 610 | simple_variant &operator =(simple_variant const &); 611 | bool const is_rvalue; 612 | aligned_storage data; 613 | }; 614 | 615 | // If the collection is an array or is noncopyable, it must be an lvalue. 616 | // If the collection is a lightweight proxy, treat it as an rvalue 617 | // BUGBUG what about a noncopyable proxy? 618 | template 619 | inline BOOST_DEDUCED_TYPENAME boost::enable_if, IsProxy>::type * 620 | should_copy_impl(LValue *, IsProxy *, bool *) 621 | { 622 | return 0; 623 | } 624 | 625 | // Otherwise, we must determine at runtime whether it's an lvalue or rvalue 626 | inline bool * 627 | should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue) 628 | { 629 | return is_rvalue; 630 | } 631 | 632 | #endif 633 | 634 | /////////////////////////////////////////////////////////////////////////////// 635 | // contain 636 | // 637 | template 638 | inline auto_any contain(T const &t, boost::mpl::true_ *) // rvalue 639 | { 640 | return auto_any(t); 641 | } 642 | 643 | template 644 | inline auto_any contain(T &t, boost::mpl::false_ *) // lvalue 645 | { 646 | // Cannot seem to get sunpro to handle addressof() with array types. 647 | #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570)) 648 | return auto_any(&t); 649 | #else 650 | return auto_any(boost::addressof(t)); 651 | #endif 652 | } 653 | 654 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 655 | template 656 | inline auto_any > 657 | contain(T const &t, bool *rvalue) 658 | { 659 | return auto_any >(*rvalue ? simple_variant(t) : simple_variant(&t)); 660 | } 661 | #endif 662 | 663 | ///////////////////////////////////////////////////////////////////////////// 664 | // begin 665 | // 666 | template 667 | inline auto_any::type> 668 | begin(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue 669 | { 670 | return auto_any::type>( 671 | boost::begin(auto_any_cast(col))); 672 | } 673 | 674 | template 675 | inline auto_any::type> 676 | begin(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue 677 | { 678 | typedef BOOST_DEDUCED_TYPENAME type2type::type type; 679 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iterator; 680 | return auto_any::type>( 681 | iterator(boost::begin(BOOST_FOREACH_DEREFOF((auto_any_cast(col)))))); 682 | } 683 | 684 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 685 | template 686 | inline auto_any::type> 687 | begin(auto_any_t col, type2type *, bool *) 688 | { 689 | return auto_any::type>( 690 | boost::begin(*auto_any_cast, boost::mpl::false_>(col).get())); 691 | } 692 | #endif 693 | 694 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 695 | template 696 | inline auto_any 697 | begin(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings 698 | { 699 | return auto_any(auto_any_cast(col)); 700 | } 701 | #endif 702 | 703 | /////////////////////////////////////////////////////////////////////////////// 704 | // end 705 | // 706 | template 707 | inline auto_any::type> 708 | end(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue 709 | { 710 | return auto_any::type>( 711 | boost::end(auto_any_cast(col))); 712 | } 713 | 714 | template 715 | inline auto_any::type> 716 | end(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue 717 | { 718 | typedef BOOST_DEDUCED_TYPENAME type2type::type type; 719 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iterator; 720 | return auto_any::type>( 721 | iterator(boost::end(BOOST_FOREACH_DEREFOF((auto_any_cast(col)))))); 722 | } 723 | 724 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 725 | template 726 | inline auto_any::type> 727 | end(auto_any_t col, type2type *, bool *) 728 | { 729 | return auto_any::type>( 730 | boost::end(*auto_any_cast, boost::mpl::false_>(col).get())); 731 | } 732 | #endif 733 | 734 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 735 | template 736 | inline auto_any 737 | end(auto_any_t, type2type *, boost::mpl::true_ *) // null-terminated C-style strings 738 | { 739 | return auto_any(0); // not used 740 | } 741 | #endif 742 | 743 | /////////////////////////////////////////////////////////////////////////////// 744 | // done 745 | // 746 | template 747 | inline bool done(auto_any_t cur, auto_any_t end, type2type *) 748 | { 749 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; 750 | return auto_any_cast(cur) == auto_any_cast(end); 751 | } 752 | 753 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 754 | template 755 | inline bool done(auto_any_t cur, auto_any_t, type2type *) // null-terminated C-style strings 756 | { 757 | return ! *auto_any_cast(cur); 758 | } 759 | #endif 760 | 761 | /////////////////////////////////////////////////////////////////////////////// 762 | // next 763 | // 764 | template 765 | inline void next(auto_any_t cur, type2type *) 766 | { 767 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; 768 | ++auto_any_cast(cur); 769 | } 770 | 771 | /////////////////////////////////////////////////////////////////////////////// 772 | // deref 773 | // 774 | template 775 | inline BOOST_DEDUCED_TYPENAME foreach_reference::type 776 | deref(auto_any_t cur, type2type *) 777 | { 778 | typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; 779 | return *auto_any_cast(cur); 780 | } 781 | 782 | ///////////////////////////////////////////////////////////////////////////// 783 | // rbegin 784 | // 785 | template 786 | inline auto_any::type> 787 | rbegin(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue 788 | { 789 | return auto_any::type>( 790 | boost::rbegin(auto_any_cast(col))); 791 | } 792 | 793 | template 794 | inline auto_any::type> 795 | rbegin(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue 796 | { 797 | typedef BOOST_DEDUCED_TYPENAME type2type::type type; 798 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iterator; 799 | return auto_any::type>( 800 | iterator(boost::rbegin(BOOST_FOREACH_DEREFOF((auto_any_cast(col)))))); 801 | } 802 | 803 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 804 | template 805 | inline auto_any::type> 806 | rbegin(auto_any_t col, type2type *, bool *) 807 | { 808 | return auto_any::type>( 809 | boost::rbegin(*auto_any_cast, boost::mpl::false_>(col).get())); 810 | } 811 | #endif 812 | 813 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 814 | template 815 | inline auto_any > 816 | rbegin(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings 817 | { 818 | T *p = auto_any_cast(col); 819 | while(0 != *p) 820 | ++p; 821 | return auto_any >(reverse_iterator(p)); 822 | } 823 | #endif 824 | 825 | /////////////////////////////////////////////////////////////////////////////// 826 | // rend 827 | // 828 | template 829 | inline auto_any::type> 830 | rend(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue 831 | { 832 | return auto_any::type>( 833 | boost::rend(auto_any_cast(col))); 834 | } 835 | 836 | template 837 | inline auto_any::type> 838 | rend(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue 839 | { 840 | typedef BOOST_DEDUCED_TYPENAME type2type::type type; 841 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iterator; 842 | return auto_any::type>( 843 | iterator(boost::rend(BOOST_FOREACH_DEREFOF((auto_any_cast(col)))))); 844 | } 845 | 846 | #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION 847 | template 848 | inline auto_any::type> 849 | rend(auto_any_t col, type2type *, bool *) 850 | { 851 | return auto_any::type>( 852 | boost::rend(*auto_any_cast, boost::mpl::false_>(col).get())); 853 | } 854 | #endif 855 | 856 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 857 | template 858 | inline auto_any > 859 | rend(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings 860 | { 861 | return auto_any >( 862 | reverse_iterator(auto_any_cast(col))); 863 | } 864 | #endif 865 | 866 | /////////////////////////////////////////////////////////////////////////////// 867 | // rdone 868 | // 869 | template 870 | inline bool rdone(auto_any_t cur, auto_any_t end, type2type *) 871 | { 872 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; 873 | return auto_any_cast(cur) == auto_any_cast(end); 874 | } 875 | 876 | /////////////////////////////////////////////////////////////////////////////// 877 | // rnext 878 | // 879 | template 880 | inline void rnext(auto_any_t cur, type2type *) 881 | { 882 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; 883 | ++auto_any_cast(cur); 884 | } 885 | 886 | /////////////////////////////////////////////////////////////////////////////// 887 | // rderef 888 | // 889 | template 890 | inline BOOST_DEDUCED_TYPENAME foreach_reference::type 891 | rderef(auto_any_t cur, type2type *) 892 | { 893 | typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; 894 | return *auto_any_cast(cur); 895 | } 896 | 897 | } // namespace foreach_detail_ 898 | } // namespace boost 899 | 900 | // Suppress a bogus code analysis warning on vc8+ 901 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) 902 | # define BOOST_FOREACH_SUPPRESS_WARNINGS() __pragma(warning(suppress:6001)) 903 | #else 904 | # define BOOST_FOREACH_SUPPRESS_WARNINGS() 905 | #endif 906 | 907 | /////////////////////////////////////////////////////////////////////////////// 908 | // Define a macro for giving hidden variables a unique name. Not strictly 909 | // needed, but eliminates some warnings on some compilers. 910 | #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 911 | // With some versions of MSVC, use of __LINE__ to create unique identifiers 912 | // can fail when the Edit-and-Continue debug flag is used. 913 | # define BOOST_FOREACH_ID(x) x 914 | #else 915 | # define BOOST_FOREACH_ID(x) BOOST_PP_CAT(x, __LINE__) 916 | #endif 917 | 918 | // A sneaky way to get the type of the collection without evaluating the expression 919 | #define BOOST_FOREACH_TYPEOF(COL) \ 920 | (true ? BOOST_FOREACH_NULL : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL))) 921 | 922 | // returns true_* if the type is noncopyable 923 | #define BOOST_FOREACH_IS_NONCOPYABLE(COL) \ 924 | boost_foreach_is_noncopyable( \ 925 | boost::foreach_detail_::to_ptr(COL) \ 926 | , boost_foreach_argument_dependent_lookup_hack_value) 927 | 928 | // returns true_* if the type is a lightweight proxy (and is not noncopyable) 929 | #define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ 930 | boost::foreach_detail_::and_( \ 931 | boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL)) \ 932 | , boost_foreach_is_lightweight_proxy( \ 933 | boost::foreach_detail_::to_ptr(COL) \ 934 | , boost_foreach_argument_dependent_lookup_hack_value)) 935 | 936 | #if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) 937 | /////////////////////////////////////////////////////////////////////////////// 938 | // R-values and const R-values supported here with zero runtime overhead 939 | /////////////////////////////////////////////////////////////////////////////// 940 | 941 | // No variable is needed to track the rvalue-ness of the collection expression 942 | # define BOOST_FOREACH_PREAMBLE() \ 943 | BOOST_FOREACH_SUPPRESS_WARNINGS() 944 | 945 | // Evaluate the collection expression 946 | # define BOOST_FOREACH_EVALUATE(COL) \ 947 | (COL) 948 | 949 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ 950 | (true ? BOOST_FOREACH_NULL : boost::foreach_detail_::or_( \ 951 | BOOST_FOREACH_IS_RVALUE(COL) \ 952 | , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))) 953 | 954 | #elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) 955 | /////////////////////////////////////////////////////////////////////////////// 956 | // R-values and const R-values supported here 957 | /////////////////////////////////////////////////////////////////////////////// 958 | 959 | // Declare a variable to track the rvalue-ness of the collection expression 960 | # define BOOST_FOREACH_PREAMBLE() \ 961 | BOOST_FOREACH_SUPPRESS_WARNINGS() \ 962 | if (bool BOOST_FOREACH_ID(_foreach_is_rvalue) = false) {} else 963 | 964 | // Evaluate the collection expression, and detect if it is an lvalue or and rvalue 965 | # define BOOST_FOREACH_EVALUATE(COL) \ 966 | (true ? boost::foreach_detail_::make_probe((COL), BOOST_FOREACH_ID(_foreach_is_rvalue)) : (COL)) 967 | 968 | // The rvalue/lvalue-ness of the collection expression is determined dynamically, unless 969 | // the type is an array or is noncopyable or is non-const, in which case we know it's an lvalue. 970 | // If the type happens to be a lightweight proxy, always make a copy. 971 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ 972 | (boost::foreach_detail_::should_copy_impl( \ 973 | true ? BOOST_FOREACH_NULL : boost::foreach_detail_::or_( \ 974 | boost::foreach_detail_::is_array_(COL) \ 975 | , BOOST_FOREACH_IS_NONCOPYABLE(COL) \ 976 | , boost::foreach_detail_::not_(boost::foreach_detail_::is_const_(COL))) \ 977 | , true ? BOOST_FOREACH_NULL : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ 978 | , &BOOST_FOREACH_ID(_foreach_is_rvalue))) 979 | 980 | #elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION) 981 | /////////////////////////////////////////////////////////////////////////////// 982 | // R-values supported here, const R-values NOT supported here 983 | /////////////////////////////////////////////////////////////////////////////// 984 | 985 | // No variable is needed to track the rvalue-ness of the collection expression 986 | # define BOOST_FOREACH_PREAMBLE() \ 987 | BOOST_FOREACH_SUPPRESS_WARNINGS() 988 | 989 | // Evaluate the collection expression 990 | # define BOOST_FOREACH_EVALUATE(COL) \ 991 | (COL) 992 | 993 | // Determine whether the collection expression is an lvalue or an rvalue. 994 | // NOTE: this gets the answer wrong for const rvalues. 995 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ 996 | (true ? BOOST_FOREACH_NULL : boost::foreach_detail_::or_( \ 997 | boost::foreach_detail_::is_rvalue_((COL), 0) \ 998 | , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))) 999 | 1000 | #else 1001 | /////////////////////////////////////////////////////////////////////////////// 1002 | // R-values NOT supported here 1003 | /////////////////////////////////////////////////////////////////////////////// 1004 | 1005 | // No variable is needed to track the rvalue-ness of the collection expression 1006 | # define BOOST_FOREACH_PREAMBLE() \ 1007 | BOOST_FOREACH_SUPPRESS_WARNINGS() 1008 | 1009 | // Evaluate the collection expression 1010 | # define BOOST_FOREACH_EVALUATE(COL) \ 1011 | (COL) 1012 | 1013 | // Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies) 1014 | # define BOOST_FOREACH_SHOULD_COPY(COL) \ 1015 | (true ? BOOST_FOREACH_NULL : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)) 1016 | 1017 | #endif 1018 | 1019 | #define BOOST_FOREACH_CONTAIN(COL) \ 1020 | boost::foreach_detail_::contain( \ 1021 | BOOST_FOREACH_EVALUATE(COL) \ 1022 | , BOOST_FOREACH_SHOULD_COPY(COL)) 1023 | 1024 | #define BOOST_FOREACH_BEGIN(COL) \ 1025 | boost::foreach_detail_::begin( \ 1026 | BOOST_FOREACH_ID(_foreach_col) \ 1027 | , BOOST_FOREACH_TYPEOF(COL) \ 1028 | , BOOST_FOREACH_SHOULD_COPY(COL)) 1029 | 1030 | #define BOOST_FOREACH_END(COL) \ 1031 | boost::foreach_detail_::end( \ 1032 | BOOST_FOREACH_ID(_foreach_col) \ 1033 | , BOOST_FOREACH_TYPEOF(COL) \ 1034 | , BOOST_FOREACH_SHOULD_COPY(COL)) 1035 | 1036 | #define BOOST_FOREACH_DONE(COL) \ 1037 | boost::foreach_detail_::done( \ 1038 | BOOST_FOREACH_ID(_foreach_cur) \ 1039 | , BOOST_FOREACH_ID(_foreach_end) \ 1040 | , BOOST_FOREACH_TYPEOF(COL)) 1041 | 1042 | #define BOOST_FOREACH_NEXT(COL) \ 1043 | boost::foreach_detail_::next( \ 1044 | BOOST_FOREACH_ID(_foreach_cur) \ 1045 | , BOOST_FOREACH_TYPEOF(COL)) 1046 | 1047 | #define BOOST_FOREACH_DEREF(COL) \ 1048 | boost::foreach_detail_::deref( \ 1049 | BOOST_FOREACH_ID(_foreach_cur) \ 1050 | , BOOST_FOREACH_TYPEOF(COL)) 1051 | 1052 | #define BOOST_FOREACH_RBEGIN(COL) \ 1053 | boost::foreach_detail_::rbegin( \ 1054 | BOOST_FOREACH_ID(_foreach_col) \ 1055 | , BOOST_FOREACH_TYPEOF(COL) \ 1056 | , BOOST_FOREACH_SHOULD_COPY(COL)) 1057 | 1058 | #define BOOST_FOREACH_REND(COL) \ 1059 | boost::foreach_detail_::rend( \ 1060 | BOOST_FOREACH_ID(_foreach_col) \ 1061 | , BOOST_FOREACH_TYPEOF(COL) \ 1062 | , BOOST_FOREACH_SHOULD_COPY(COL)) 1063 | 1064 | #define BOOST_FOREACH_RDONE(COL) \ 1065 | boost::foreach_detail_::rdone( \ 1066 | BOOST_FOREACH_ID(_foreach_cur) \ 1067 | , BOOST_FOREACH_ID(_foreach_end) \ 1068 | , BOOST_FOREACH_TYPEOF(COL)) 1069 | 1070 | #define BOOST_FOREACH_RNEXT(COL) \ 1071 | boost::foreach_detail_::rnext( \ 1072 | BOOST_FOREACH_ID(_foreach_cur) \ 1073 | , BOOST_FOREACH_TYPEOF(COL)) 1074 | 1075 | #define BOOST_FOREACH_RDEREF(COL) \ 1076 | boost::foreach_detail_::rderef( \ 1077 | BOOST_FOREACH_ID(_foreach_cur) \ 1078 | , BOOST_FOREACH_TYPEOF(COL)) 1079 | 1080 | /////////////////////////////////////////////////////////////////////////////// 1081 | // BOOST_FOREACH 1082 | // 1083 | // For iterating over collections. Collections can be 1084 | // arrays, null-terminated strings, or STL containers. 1085 | // The loop variable can be a value or reference. For 1086 | // example: 1087 | // 1088 | // std::list int_list(/*stuff*/); 1089 | // BOOST_FOREACH(int &i, int_list) 1090 | // { 1091 | // /* 1092 | // * loop body goes here. 1093 | // * i is a reference to the int in int_list. 1094 | // */ 1095 | // } 1096 | // 1097 | // Alternately, you can declare the loop variable first, 1098 | // so you can access it after the loop finishes. Obviously, 1099 | // if you do it this way, then the loop variable cannot be 1100 | // a reference. 1101 | // 1102 | // int i; 1103 | // BOOST_FOREACH(i, int_list) 1104 | // { ... } 1105 | // 1106 | #define BOOST_FOREACH(VAR, COL) \ 1107 | BOOST_FOREACH_PREAMBLE() \ 1108 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ 1109 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \ 1110 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \ 1111 | for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ 1112 | BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \ 1113 | BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \ 1114 | if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ 1115 | for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) 1116 | 1117 | /////////////////////////////////////////////////////////////////////////////// 1118 | // BOOST_REVERSE_FOREACH 1119 | // 1120 | // For iterating over collections in reverse order. In 1121 | // all other respects, BOOST_REVERSE_FOREACH is like 1122 | // BOOST_FOREACH. 1123 | // 1124 | #define BOOST_REVERSE_FOREACH(VAR, COL) \ 1125 | BOOST_FOREACH_PREAMBLE() \ 1126 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ 1127 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) {} else \ 1128 | if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL)) {} else \ 1129 | for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ 1130 | BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_RDONE(COL); \ 1131 | BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \ 1132 | if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ 1133 | for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) 1134 | 1135 | #endif 1136 | -------------------------------------------------------------------------------- /include/boost/foreach_fwd.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // foreach.hpp header file 3 | // 4 | // Copyright 2010 Eric Niebler. 5 | // Distributed under the Boost Software License, Version 1.0. (See 6 | // accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | // See http://www.boost.org/libs/foreach for documentation 9 | // 10 | // Credits: 11 | // Kazutoshi Satoda: for suggesting the need for a _fwd header for foreach's 12 | // customization points. 13 | 14 | #ifndef BOOST_FOREACH_FWD_HPP 15 | #define BOOST_FOREACH_FWD_HPP 16 | 17 | // This must be at global scope, hence the uglified name 18 | enum boost_foreach_argument_dependent_lookup_hack 19 | { 20 | boost_foreach_argument_dependent_lookup_hack_value 21 | }; 22 | 23 | namespace boost 24 | { 25 | 26 | namespace foreach 27 | { 28 | /////////////////////////////////////////////////////////////////////////////// 29 | // boost::foreach::tag 30 | // 31 | typedef boost_foreach_argument_dependent_lookup_hack tag; 32 | 33 | /////////////////////////////////////////////////////////////////////////////// 34 | // boost::foreach::is_lightweight_proxy 35 | // Specialize this for user-defined collection types if they are inexpensive to copy. 36 | // This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff. 37 | template 38 | struct is_lightweight_proxy; 39 | 40 | /////////////////////////////////////////////////////////////////////////////// 41 | // boost::foreach::is_noncopyable 42 | // Specialize this for user-defined collection types if they cannot be copied. 43 | // This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff. 44 | template 45 | struct is_noncopyable; 46 | 47 | } // namespace foreach 48 | 49 | } // namespace boost 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Automatic redirection failed, please go to 7 | ../../doc/html/foreach.html 8 |

Copyright Eric Niebler 2006

9 |

Distributed under the Boost Software License, Version 1.0. (See accompanying file 10 | LICENSE_1_0.txt or copy at 11 | www.boost.org/LICENSE_1_0.txt). 12 |

13 | 14 | 15 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "foreach", 3 | "name": "Foreach", 4 | "authors": [ 5 | "Eric Niebler" 6 | ], 7 | "description": "In C++, writing a loop that iterates over a sequence is tedious. We can either use iterators, which requires a considerable amount of boiler-plate, or we can use the std::for_each() algorithm and move our loop body into a predicate, which requires no less boiler-plate and forces us to move our logic far from where it will be used. In contrast, some other languages, like Perl, provide a dedicated \"foreach\" construct that automates this process. BOOST_FOREACH is just such a construct for C++. It iterates over sequences for us, freeing us from having to deal directly with iterators or write predicates.", 8 | "category": [ 9 | "Algorithms", 10 | "Emulation" 11 | ], 12 | "maintainers": [ 13 | "Eric Niebler " 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /test/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # (C) Copyright 2004: Eric Niebler 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 | 5 | # bring in rules for testing 6 | import testing ; 7 | 8 | project : requirements msvc:on 9 | /boost/foreach//boost_foreach ; 10 | 11 | test-suite "foreach" 12 | : [ run stl_byval.cpp ] 13 | [ run stl_byref.cpp ] 14 | [ run stl_byval_r.cpp ] 15 | [ run stl_byref_r.cpp ] 16 | [ run array_byval.cpp ] 17 | [ run array_byref.cpp ] 18 | [ run array_byval_r.cpp ] 19 | [ run array_byref_r.cpp ] 20 | [ run cstr_byval.cpp ] 21 | [ run cstr_byref.cpp ] 22 | [ run cstr_byval_r.cpp ] 23 | [ run cstr_byref_r.cpp ] 24 | [ run pair_byval.cpp ] 25 | [ run pair_byref.cpp ] 26 | [ run pair_byval_r.cpp ] 27 | [ run pair_byref_r.cpp ] 28 | [ run user_defined.cpp ] 29 | [ run call_once.cpp ] 30 | [ run rvalue_const.cpp ] 31 | [ run rvalue_nonconst.cpp ] 32 | [ run rvalue_const_r.cpp ] 33 | [ run rvalue_nonconst_r.cpp ] 34 | [ run dependent_type.cpp ] 35 | [ run misc.cpp ] 36 | [ compile noncopyable.cpp ] 37 | ; 38 | -------------------------------------------------------------------------------- /test/array_byref.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef int foreach_container_type[5]; 17 | typedef int const foreach_const_container_type[5]; 18 | typedef int foreach_value_type; 19 | typedef int &foreach_reference_type; 20 | typedef int const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | int my_array[5] = { 1,2,3,4,5 }; 28 | int const (&my_const_array)[5] = my_array; 29 | 30 | /////////////////////////////////////////////////////////////////////////////// 31 | // test_main 32 | // 33 | int main() 34 | { 35 | // non-const containers by reference 36 | BOOST_TEST(sequence_equal_byref_n(my_array, "\1\2\3\4\5")); 37 | 38 | // const containers by reference 39 | BOOST_TEST(sequence_equal_byref_c(my_const_array, "\1\2\3\4\5")); 40 | 41 | // mutate the mutable collections 42 | mutate_foreach_byref(my_array); 43 | 44 | // compare the mutated collections to the actual results 45 | BOOST_TEST(sequence_equal_byref_n(my_array, "\2\3\4\5\6")); 46 | 47 | return boost::report_errors(); 48 | } 49 | -------------------------------------------------------------------------------- /test/array_byref_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef int foreach_container_type[5]; 17 | typedef int const foreach_const_container_type[5]; 18 | typedef int foreach_value_type; 19 | typedef int &foreach_reference_type; 20 | typedef int const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | int my_array[5] = { 1,2,3,4,5 }; 28 | int const (&my_const_array)[5] = my_array; 29 | 30 | /////////////////////////////////////////////////////////////////////////////// 31 | // test_main 32 | // 33 | int main() 34 | { 35 | // non-const containers by reference 36 | BOOST_TEST(sequence_equal_byref_n_r(my_array, "\5\4\3\2\1")); 37 | 38 | // const containers by reference 39 | BOOST_TEST(sequence_equal_byref_c_r(my_const_array, "\5\4\3\2\1")); 40 | 41 | // mutate the mutable collections 42 | mutate_foreach_byref_r(my_array); 43 | 44 | // compare the mutated collections to the actual results 45 | BOOST_TEST(sequence_equal_byref_n_r(my_array, "\6\5\4\3\2")); 46 | 47 | return boost::report_errors(); 48 | } 49 | -------------------------------------------------------------------------------- /test/array_byval.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef int foreach_container_type[5]; 17 | typedef int const foreach_const_container_type[5]; 18 | typedef int foreach_value_type; 19 | typedef int &foreach_reference_type; 20 | typedef int const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | int my_array[5] = { 1,2,3,4,5 }; 28 | int const (&my_const_array)[5] = my_array; 29 | 30 | /////////////////////////////////////////////////////////////////////////////// 31 | // test_main 32 | // 33 | int main() 34 | { 35 | boost::mpl::false_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_array); 36 | (void)p; 37 | // non-const containers by value 38 | BOOST_TEST(sequence_equal_byval_n(my_array, "\1\2\3\4\5")); 39 | 40 | // const containers by value 41 | BOOST_TEST(sequence_equal_byval_c(my_const_array, "\1\2\3\4\5")); 42 | 43 | return boost::report_errors(); 44 | } 45 | -------------------------------------------------------------------------------- /test/array_byval_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef int foreach_container_type[5]; 17 | typedef int const foreach_const_container_type[5]; 18 | typedef int foreach_value_type; 19 | typedef int &foreach_reference_type; 20 | typedef int const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | int my_array[5] = { 1,2,3,4,5 }; 28 | int const (&my_const_array)[5] = my_array; 29 | 30 | /////////////////////////////////////////////////////////////////////////////// 31 | // test_main 32 | // 33 | int main() 34 | { 35 | boost::mpl::false_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_array); 36 | (void)p; 37 | 38 | // non-const containers by value 39 | BOOST_TEST(sequence_equal_byval_n_r(my_array, "\5\4\3\2\1")); 40 | 41 | // const containers by value 42 | BOOST_TEST(sequence_equal_byval_c_r(my_const_array, "\5\4\3\2\1")); 43 | 44 | return boost::report_errors(); 45 | } 46 | -------------------------------------------------------------------------------- /test/call_once.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // counter 16 | int counter = 0; 17 | 18 | std::vector my_vector(4,4); 19 | 20 | std::vector const &get_vector() 21 | { 22 | ++counter; 23 | return my_vector; 24 | } 25 | 26 | 27 | /////////////////////////////////////////////////////////////////////////////// 28 | // test_main 29 | // 30 | int main() 31 | { 32 | BOOST_FOREACH(int i, get_vector()) 33 | { 34 | ((void)i); // no-op 35 | } 36 | 37 | BOOST_TEST(1 == counter); 38 | 39 | return boost::report_errors(); 40 | } 41 | -------------------------------------------------------------------------------- /test/cstr_byref.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef char *foreach_container_type; 17 | typedef char const *foreach_const_container_type; 18 | typedef char foreach_value_type; 19 | typedef char &foreach_reference_type; 20 | typedef char const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | char my_ntcs_buffer[] = "\1\2\3\4\5"; 28 | char *my_ntcs = my_ntcs_buffer; 29 | char const *my_const_ntcs = my_ntcs; 30 | 31 | /////////////////////////////////////////////////////////////////////////////// 32 | // test_main 33 | // 34 | int main() 35 | { 36 | // non-const containers by reference 37 | BOOST_TEST(sequence_equal_byref_n(my_ntcs, "\1\2\3\4\5")); 38 | 39 | // const containers by reference 40 | BOOST_TEST(sequence_equal_byref_c(my_const_ntcs, "\1\2\3\4\5")); 41 | 42 | // mutate the mutable collections 43 | mutate_foreach_byref(my_ntcs); 44 | 45 | // compare the mutated collections to the actual results 46 | BOOST_TEST(sequence_equal_byref_n(my_ntcs, "\2\3\4\5\6")); 47 | 48 | return boost::report_errors(); 49 | } 50 | -------------------------------------------------------------------------------- /test/cstr_byref_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef char *foreach_container_type; 17 | typedef char const *foreach_const_container_type; 18 | typedef char foreach_value_type; 19 | typedef char &foreach_reference_type; 20 | typedef char const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | char my_ntcs_buffer[] = "\1\2\3\4\5"; 28 | char *my_ntcs = my_ntcs_buffer; 29 | char const *my_const_ntcs = my_ntcs; 30 | 31 | /////////////////////////////////////////////////////////////////////////////// 32 | // test_main 33 | // 34 | int main() 35 | { 36 | // non-const containers by reference 37 | BOOST_TEST(sequence_equal_byref_n_r(my_ntcs, "\5\4\3\2\1")); 38 | 39 | // const containers by reference 40 | BOOST_TEST(sequence_equal_byref_c_r(my_const_ntcs, "\5\4\3\2\1")); 41 | 42 | // mutate the mutable collections 43 | mutate_foreach_byref_r(my_ntcs); 44 | 45 | // compare the mutated collections to the actual results 46 | BOOST_TEST(sequence_equal_byref_n_r(my_ntcs, "\6\5\4\3\2")); 47 | 48 | return boost::report_errors(); 49 | } 50 | -------------------------------------------------------------------------------- /test/cstr_byval.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef char *foreach_container_type; 17 | typedef char const *foreach_const_container_type; 18 | typedef char foreach_value_type; 19 | typedef char &foreach_reference_type; 20 | typedef char const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | char my_ntcs_buffer[] = "\1\2\3\4\5"; 28 | char *my_ntcs = my_ntcs_buffer; 29 | char const *my_const_ntcs = my_ntcs; 30 | 31 | /////////////////////////////////////////////////////////////////////////////// 32 | // test_main 33 | // 34 | int main() 35 | { 36 | boost::mpl::true_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_ntcs); 37 | (void)p; 38 | 39 | // non-const containers by value 40 | BOOST_TEST(sequence_equal_byval_n(my_ntcs, "\1\2\3\4\5")); 41 | 42 | // const containers by value 43 | BOOST_TEST(sequence_equal_byval_c(my_const_ntcs, "\1\2\3\4\5")); 44 | 45 | return boost::report_errors(); 46 | } 47 | -------------------------------------------------------------------------------- /test/cstr_byval_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef char *foreach_container_type; 17 | typedef char const *foreach_const_container_type; 18 | typedef char foreach_value_type; 19 | typedef char &foreach_reference_type; 20 | typedef char const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | char my_ntcs_buffer[] = "\1\2\3\4\5"; 28 | char *my_ntcs = my_ntcs_buffer; 29 | char const *my_const_ntcs = my_ntcs; 30 | 31 | /////////////////////////////////////////////////////////////////////////////// 32 | // test_main 33 | // 34 | int main() 35 | { 36 | boost::mpl::true_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_ntcs); 37 | (void)p; 38 | 39 | // non-const containers by value 40 | BOOST_TEST(sequence_equal_byval_n_r(my_ntcs, "\5\4\3\2\1")); 41 | 42 | // const containers by value 43 | BOOST_TEST(sequence_equal_byval_c_r(my_const_ntcs, "\5\4\3\2\1")); 44 | 45 | return boost::report_errors(); 46 | } 47 | -------------------------------------------------------------------------------- /test/dependent_type.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 26 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | // use FOREACH to iterate over a sequence with a dependent type 17 | template 18 | void do_test(Vector const & vect) 19 | { 20 | typedef BOOST_DEDUCED_TYPENAME Vector::value_type value_type; 21 | BOOST_FOREACH(value_type i, vect) 22 | { 23 | // no-op, just make sure this compiles 24 | ((void)i); 25 | } 26 | } 27 | 28 | /////////////////////////////////////////////////////////////////////////////// 29 | // test_main 30 | // 31 | int main() 32 | { 33 | std::vector vect; 34 | do_test(vect); 35 | 36 | return boost::report_errors(); 37 | } 38 | -------------------------------------------------------------------------------- /test/misc.cpp: -------------------------------------------------------------------------------- 1 | // misc.cpp 2 | // 3 | // (C) Copyright Eric Niebler 2008. 4 | // Use, modification and distribution are subject to the 5 | // Boost Software License, Version 1.0. (See accompanying file 6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | /* 9 | Revision history: 10 | 4 March 2008 : Initial version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | struct xxx : std::vector 18 | { 19 | virtual ~xxx() = 0; 20 | }; 21 | 22 | void test_abstract(xxx& rng) 23 | { 24 | BOOST_FOREACH (int x, rng) 25 | { 26 | (void)x; 27 | } 28 | } 29 | 30 | struct yyy : std::vector 31 | { 32 | void test() 33 | { 34 | BOOST_FOREACH(int x, *this) 35 | { 36 | (void)x; 37 | } 38 | } 39 | }; 40 | 41 | /////////////////////////////////////////////////////////////////////////////// 42 | // test_main 43 | // 44 | int main() 45 | { 46 | return boost::report_errors(); 47 | } 48 | -------------------------------------------------------------------------------- /test/noncopyable.cpp: -------------------------------------------------------------------------------- 1 | // noncopyable.cpp 2 | /// 3 | // (C) Copyright Eric Niebler 2004. 4 | // Use, modification and distribution are subject to the 5 | // Boost Software License, Version 1.0. (See accompanying file 6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | /* 9 | Revision history: 10 | 21 December 2005 : Initial version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | struct noncopy_vector 19 | : std::vector 20 | , private boost::noncopyable 21 | { 22 | noncopy_vector() { } 23 | }; 24 | 25 | struct noncopy_range 26 | : boost::iterator_range 27 | , private boost::noncopyable 28 | { 29 | noncopy_range() { } 30 | }; 31 | 32 | // Tell FOREACH that noncopy_vector and noncopy_range are non-copyable. 33 | // NOTE: this is only necessary if 34 | // a) your type does not inherit from boost::noncopyable, OR 35 | // b) Boost.Config defines BOOST_BROKEN_IS_BASE_AND_DERIVED for your compiler 36 | #ifdef BOOST_BROKEN_IS_BASE_AND_DERIVED 37 | inline boost::mpl::true_ *boost_foreach_is_noncopyable(noncopy_vector *&, boost::foreach::tag) 38 | { 39 | return 0; 40 | } 41 | 42 | inline boost::mpl::true_ *boost_foreach_is_noncopyable(noncopy_range *&, boost::foreach::tag) 43 | { 44 | return 0; 45 | } 46 | #endif 47 | 48 | // tell FOREACH that noncopy_range is a lightweight proxy object 49 | inline boost::mpl::true_ *boost_foreach_is_lightweight_proxy(noncopy_range *&, boost::foreach::tag) 50 | { 51 | return 0; 52 | } 53 | 54 | /////////////////////////////////////////////////////////////////////////////// 55 | // main 56 | // 57 | int main( int, char*[] ) 58 | { 59 | noncopy_vector v1; 60 | BOOST_FOREACH( int & i, v1 ) { (void)i; } 61 | 62 | noncopy_vector const v2; 63 | BOOST_FOREACH( int const & j, v2 ) { (void)j; } 64 | 65 | noncopy_range rng1; 66 | BOOST_FOREACH( int & k, rng1 ) { (void)k; } 67 | 68 | noncopy_range const rng2; 69 | BOOST_FOREACH( int & l, rng2 ) { (void)l; } 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /test/pair_byref.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 13 December 2004 : Initial version. 9 | 25 August 2005 : Initial version. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | // define the container types, used by utility.hpp to generate the helper functions 17 | typedef std::pair foreach_container_type; 18 | typedef std::pair const foreach_const_container_type; 19 | typedef int foreach_value_type; 20 | typedef int &foreach_reference_type; 21 | typedef int const &foreach_const_reference_type; 22 | 23 | #include "./utility.hpp" 24 | 25 | /////////////////////////////////////////////////////////////////////////////// 26 | // define some containers 27 | // 28 | int my_array[] = { 1,2,3,4,5 }; 29 | std::pair my_pair(my_array,my_array+5); 30 | std::pair const my_const_pair(my_array,my_array+5); 31 | 32 | /////////////////////////////////////////////////////////////////////////////// 33 | // test_main 34 | // 35 | int main() 36 | { 37 | // non-const containers by reference 38 | BOOST_TEST(sequence_equal_byref_n(my_pair, "\1\2\3\4\5")); 39 | 40 | // const containers by reference 41 | BOOST_TEST(sequence_equal_byref_c(my_const_pair, "\1\2\3\4\5")); 42 | 43 | // mutate the mutable collections 44 | mutate_foreach_byref(my_pair); 45 | 46 | // compare the mutated collections to the actual results 47 | BOOST_TEST(sequence_equal_byref_n(my_pair, "\2\3\4\5\6")); 48 | 49 | return boost::report_errors(); 50 | } 51 | -------------------------------------------------------------------------------- /test/pair_byref_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 13 December 2004 : Initial version. 9 | 25 August 2005 : Initial version. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | // define the container types, used by utility.hpp to generate the helper functions 17 | typedef std::pair foreach_container_type; 18 | typedef std::pair const foreach_const_container_type; 19 | typedef int foreach_value_type; 20 | typedef int &foreach_reference_type; 21 | typedef int const &foreach_const_reference_type; 22 | 23 | #include "./utility.hpp" 24 | 25 | /////////////////////////////////////////////////////////////////////////////// 26 | // define some containers 27 | // 28 | int my_array[] = { 1,2,3,4,5 }; 29 | std::pair my_pair(my_array,my_array+5); 30 | std::pair const my_const_pair(my_array,my_array+5); 31 | 32 | /////////////////////////////////////////////////////////////////////////////// 33 | // test_main 34 | // 35 | int main() 36 | { 37 | // non-const containers by reference 38 | BOOST_TEST(sequence_equal_byref_n_r(my_pair, "\5\4\3\2\1")); 39 | 40 | // const containers by reference 41 | BOOST_TEST(sequence_equal_byref_c_r(my_const_pair, "\5\4\3\2\1")); 42 | 43 | // mutate the mutable collections 44 | mutate_foreach_byref_r(my_pair); 45 | 46 | // compare the mutated collections to the actual results 47 | BOOST_TEST(sequence_equal_byref_n_r(my_pair, "\6\5\4\3\2")); 48 | 49 | return boost::report_errors(); 50 | } 51 | -------------------------------------------------------------------------------- /test/pair_byval.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef std::pair foreach_container_type; 17 | typedef std::pair const foreach_const_container_type; 18 | typedef int foreach_value_type; 19 | typedef int &foreach_reference_type; 20 | typedef int const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | int my_array[] = { 1,2,3,4,5 }; 28 | std::pair my_pair(my_array,my_array+5); 29 | std::pair const my_const_pair(my_array,my_array+5); 30 | 31 | /////////////////////////////////////////////////////////////////////////////// 32 | // test_main 33 | // 34 | int main() 35 | { 36 | boost::mpl::true_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_pair); 37 | (void)p; 38 | 39 | // non-const containers by value 40 | BOOST_TEST(sequence_equal_byval_n(my_pair, "\1\2\3\4\5")); 41 | 42 | // const containers by value 43 | BOOST_TEST(sequence_equal_byval_c(my_const_pair, "\1\2\3\4\5")); 44 | 45 | return boost::report_errors(); 46 | } 47 | -------------------------------------------------------------------------------- /test/pair_byval_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // define the container types, used by utility.hpp to generate the helper functions 16 | typedef std::pair foreach_container_type; 17 | typedef std::pair const foreach_const_container_type; 18 | typedef int foreach_value_type; 19 | typedef int &foreach_reference_type; 20 | typedef int const &foreach_const_reference_type; 21 | 22 | #include "./utility.hpp" 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // define some containers 26 | // 27 | int my_array[] = { 1,2,3,4,5 }; 28 | std::pair my_pair(my_array,my_array+5); 29 | std::pair const my_const_pair(my_array,my_array+5); 30 | 31 | /////////////////////////////////////////////////////////////////////////////// 32 | // test_main 33 | // 34 | int main() 35 | { 36 | boost::mpl::true_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_pair); 37 | (void)p; 38 | 39 | // non-const containers by value 40 | BOOST_TEST(sequence_equal_byval_n_r(my_pair, "\5\4\3\2\1")); 41 | 42 | // const containers by value 43 | BOOST_TEST(sequence_equal_byval_c_r(my_const_pair, "\5\4\3\2\1")); 44 | 45 | return boost::report_errors(); 46 | } 47 | -------------------------------------------------------------------------------- /test/rvalue_const.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION 16 | // ignore error during Microsoft Code Analysis 17 | #if !defined(_PREFAST_) 18 | # error Expected failure : const rvalues disallowed 19 | #endif 20 | #else 21 | 22 | std::vector const get_vector() 23 | { 24 | return std::vector(4, 4); 25 | } 26 | 27 | /////////////////////////////////////////////////////////////////////////////// 28 | // test_main 29 | // 30 | int main() 31 | { 32 | int counter = 0; 33 | 34 | BOOST_FOREACH(int i, get_vector()) 35 | { 36 | counter += i; 37 | } 38 | 39 | BOOST_TEST(16 == counter); 40 | 41 | return boost::report_errors(); 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /test/rvalue_const_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION 16 | // ignore error during Microsoft Code Analysis 17 | #if !defined(_PREFAST_) 18 | # error Expected failure : const rvalues disallowed 19 | #endif 20 | #else 21 | 22 | std::vector const get_vector() 23 | { 24 | return std::vector(4, 4); 25 | } 26 | 27 | /////////////////////////////////////////////////////////////////////////////// 28 | // test_main 29 | // 30 | int main() 31 | { 32 | int counter = 0; 33 | 34 | BOOST_REVERSE_FOREACH(int i, get_vector()) 35 | { 36 | counter += i; 37 | } 38 | 39 | BOOST_TEST(16 == counter); 40 | 41 | return boost::report_errors(); 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /test/rvalue_nonconst.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef BOOST_FOREACH_NO_RVALUE_DETECTION 16 | # error Expected failure : rvalues disallowed 17 | #else 18 | 19 | std::vector get_vector() 20 | { 21 | return std::vector(4, 4); 22 | } 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // test_main 26 | // 27 | int main() 28 | { 29 | int counter = 0; 30 | 31 | BOOST_FOREACH(int i, get_vector()) 32 | { 33 | counter += i; 34 | } 35 | 36 | BOOST_TEST(16 == counter); 37 | 38 | return boost::report_errors(); 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /test/rvalue_nonconst_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef BOOST_FOREACH_NO_RVALUE_DETECTION 16 | # error Expected failure : rvalues disallowed 17 | #else 18 | 19 | std::vector get_vector() 20 | { 21 | return std::vector(4, 4); 22 | } 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // test_main 26 | // 27 | int main() 28 | { 29 | int counter = 0; 30 | 31 | BOOST_REVERSE_FOREACH(int i, get_vector()) 32 | { 33 | counter += i; 34 | } 35 | 36 | BOOST_TEST(16 == counter); 37 | 38 | return boost::report_errors(); 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /test/stl_byref.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005: Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | // define the container types, used by utility.hpp to generate the helper functions 17 | typedef std::list foreach_container_type; 18 | typedef std::list const foreach_const_container_type; 19 | typedef int foreach_value_type; 20 | typedef int &foreach_reference_type; 21 | typedef int const &foreach_const_reference_type; 22 | 23 | #include "./utility.hpp" 24 | 25 | /////////////////////////////////////////////////////////////////////////////// 26 | // initialize a std::list 27 | std::list make_list() 28 | { 29 | std::list l; 30 | l.push_back(1); 31 | l.push_back(2); 32 | l.push_back(3); 33 | l.push_back(4); 34 | l.push_back(5); 35 | return l; 36 | } 37 | 38 | /////////////////////////////////////////////////////////////////////////////// 39 | // define some containers 40 | // 41 | std::list my_list = make_list(); 42 | std::list const &my_const_list = my_list; 43 | 44 | /////////////////////////////////////////////////////////////////////////////// 45 | // test_main 46 | // 47 | int main() 48 | { 49 | // non-const containers by reference 50 | BOOST_TEST(sequence_equal_byref_n(my_list, "\1\2\3\4\5")); 51 | 52 | // const containers by reference 53 | BOOST_TEST(sequence_equal_byref_c(my_const_list, "\1\2\3\4\5")); 54 | 55 | // mutate the mutable collections 56 | mutate_foreach_byref(my_list); 57 | 58 | // compare the mutated collections to the actual results 59 | BOOST_TEST(sequence_equal_byref_n(my_list, "\2\3\4\5\6")); 60 | 61 | return boost::report_errors(); 62 | } 63 | -------------------------------------------------------------------------------- /test/stl_byref_r.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2004. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005: Initial version. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | // define the container types, used by utility.hpp to generate the helper functions 17 | typedef std::list foreach_container_type; 18 | typedef std::list const foreach_const_container_type; 19 | typedef int foreach_value_type; 20 | typedef int &foreach_reference_type; 21 | typedef int const &foreach_const_reference_type; 22 | 23 | #include "./utility.hpp" 24 | 25 | /////////////////////////////////////////////////////////////////////////////// 26 | // initialize a std::list 27 | std::list make_list() 28 | { 29 | std::list l; 30 | l.push_back(1); 31 | l.push_back(2); 32 | l.push_back(3); 33 | l.push_back(4); 34 | l.push_back(5); 35 | return l; 36 | } 37 | 38 | /////////////////////////////////////////////////////////////////////////////// 39 | // define some containers 40 | // 41 | std::list my_list = make_list(); 42 | std::list const &my_const_list = my_list; 43 | 44 | /////////////////////////////////////////////////////////////////////////////// 45 | // test_main 46 | // 47 | int main() 48 | { 49 | // non-const containers by reference 50 | BOOST_TEST(sequence_equal_byref_n_r(my_list, "\5\4\3\2\1")); 51 | 52 | // const containers by reference 53 | BOOST_TEST(sequence_equal_byref_c_r(my_const_list, "\5\4\3\2\1")); 54 | 55 | // mutate the mutable collections 56 | mutate_foreach_byref_r(my_list); 57 | 58 | // compare the mutated collections to the actual results 59 | BOOST_TEST(sequence_equal_byref_n_r(my_list, "\6\5\4\3\2")); 60 | 61 | return boost::report_errors(); 62 | } 63 | -------------------------------------------------------------------------------- /test/stl_byval.cpp: -------------------------------------------------------------------------------- 1 | // stl_byval.cpp 2 | /// 3 | // (C) Copyright Eric Niebler 2004. 4 | // Use, modification and distribution are subject to the 5 | // Boost Software License, Version 1.0. (See accompanying file 6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | /* 9 | Revision history: 10 | 25 August 2005 : Initial version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | /////////////////////////////////////////////////////////////////////////////// 18 | // define the container types, used by utility.hpp to generate the helper functions 19 | typedef std::list foreach_container_type; 20 | typedef std::list const foreach_const_container_type; 21 | typedef int foreach_value_type; 22 | typedef int &foreach_reference_type; 23 | typedef int const &foreach_const_reference_type; 24 | 25 | #include "./utility.hpp" 26 | 27 | /////////////////////////////////////////////////////////////////////////////// 28 | // initialize a std::list 29 | std::list make_list() 30 | { 31 | std::list l; 32 | l.push_back(1); 33 | l.push_back(2); 34 | l.push_back(3); 35 | l.push_back(4); 36 | l.push_back(5); 37 | return l; 38 | } 39 | 40 | /////////////////////////////////////////////////////////////////////////////// 41 | // define some containers 42 | // 43 | std::list my_list = make_list(); 44 | std::list const &my_const_list = my_list; 45 | 46 | /////////////////////////////////////////////////////////////////////////////// 47 | // test_main 48 | // 49 | int main() 50 | { 51 | boost::mpl::false_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_list); 52 | (void)p; 53 | 54 | // non-const containers by value 55 | BOOST_TEST(sequence_equal_byval_n(my_list, "\1\2\3\4\5")); 56 | 57 | // const containers by value 58 | BOOST_TEST(sequence_equal_byval_c(my_const_list, "\1\2\3\4\5")); 59 | 60 | return boost::report_errors(); 61 | } 62 | -------------------------------------------------------------------------------- /test/stl_byval_r.cpp: -------------------------------------------------------------------------------- 1 | // stl_byval.cpp 2 | /// 3 | // (C) Copyright Eric Niebler 2004. 4 | // Use, modification and distribution are subject to the 5 | // Boost Software License, Version 1.0. (See accompanying file 6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | /* 9 | Revision history: 10 | 25 August 2005 : Initial version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | /////////////////////////////////////////////////////////////////////////////// 18 | // define the container types, used by utility.hpp to generate the helper functions 19 | typedef std::list foreach_container_type; 20 | typedef std::list const foreach_const_container_type; 21 | typedef int foreach_value_type; 22 | typedef int &foreach_reference_type; 23 | typedef int const &foreach_const_reference_type; 24 | 25 | #include "./utility.hpp" 26 | 27 | /////////////////////////////////////////////////////////////////////////////// 28 | // initialize a std::list 29 | std::list make_list() 30 | { 31 | std::list l; 32 | l.push_back(1); 33 | l.push_back(2); 34 | l.push_back(3); 35 | l.push_back(4); 36 | l.push_back(5); 37 | return l; 38 | } 39 | 40 | /////////////////////////////////////////////////////////////////////////////// 41 | // define some containers 42 | // 43 | std::list my_list = make_list(); 44 | std::list const &my_const_list = my_list; 45 | 46 | /////////////////////////////////////////////////////////////////////////////// 47 | // test_main 48 | // 49 | int main() 50 | { 51 | boost::mpl::false_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_list); 52 | (void)p; 53 | 54 | // non-const containers by value 55 | BOOST_TEST(sequence_equal_byval_n_r(my_list, "\5\4\3\2\1")); 56 | 57 | // const containers by value 58 | BOOST_TEST(sequence_equal_byval_c_r(my_const_list, "\5\4\3\2\1")); 59 | 60 | return boost::report_errors(); 61 | } 62 | -------------------------------------------------------------------------------- /test/user_defined.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Eric Niebler 2005. 2 | // Use, modification and distribution are subject to the 3 | // Boost Software License, Version 1.0. (See accompanying file 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | /* 7 | Revision history: 8 | 25 August 2005 : Initial version. 9 | */ 10 | 11 | #include 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | // define a user-defined collection type and teach BOOST_FOREACH how to enumerate it 15 | // 16 | namespace mine 17 | { 18 | struct dummy {}; 19 | char * range_begin(mine::dummy&) {return 0;} 20 | char const * range_begin(mine::dummy const&) {return 0;} 21 | char * range_end(mine::dummy&) {return 0;} 22 | char const * range_end(mine::dummy const&) {return 0;} 23 | } 24 | 25 | #include 26 | 27 | namespace boost 28 | { 29 | template<> 30 | struct range_mutable_iterator 31 | { 32 | typedef char * type; 33 | }; 34 | template<> 35 | struct range_const_iterator 36 | { 37 | typedef char const * type; 38 | }; 39 | } 40 | 41 | /////////////////////////////////////////////////////////////////////////////// 42 | // test_main 43 | // 44 | int main() 45 | { 46 | // loop over a user-defined type (just make sure this compiles) 47 | mine::dummy d; 48 | BOOST_FOREACH( char c, d ) 49 | { 50 | ((void)c); // no-op 51 | } 52 | 53 | return boost::report_errors(); 54 | } 55 | -------------------------------------------------------------------------------- /test/utility.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // utility.hpp header file 3 | // 4 | // Copyright 2005 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 | 10 | #ifndef BOOST_FOREACH_TEST_UTILITY_HPP 11 | #define BOOST_FOREACH_TEST_UTILITY_HPP 12 | 13 | #include 14 | #include 15 | 16 | /////////////////////////////////////////////////////////////////////////////// 17 | // sequence_equal_byval_n 18 | inline bool sequence_equal_byval_n( foreach_container_type & rng, char const * result ) 19 | { 20 | BOOST_FOREACH( foreach_value_type i, rng ) 21 | { 22 | if(0 == *result || i != *result) 23 | return false; 24 | ++result; 25 | } 26 | return 0 == *result; 27 | } 28 | 29 | /////////////////////////////////////////////////////////////////////////////// 30 | // sequence_equal_byval_c 31 | inline bool sequence_equal_byval_c( foreach_const_container_type & rng, char const * result ) 32 | { 33 | BOOST_FOREACH( foreach_value_type i, rng ) 34 | { 35 | if(0 == *result || i != *result) 36 | return false; 37 | ++result; 38 | } 39 | return 0 == *result; 40 | } 41 | 42 | /////////////////////////////////////////////////////////////////////////////// 43 | // sequence_equal_byref_n 44 | inline bool sequence_equal_byref_n( foreach_container_type & rng, char const * result ) 45 | { 46 | BOOST_FOREACH( foreach_reference_type i, rng ) 47 | { 48 | if(0 == *result || i != *result) 49 | return false; 50 | ++result; 51 | } 52 | return 0 == *result; 53 | } 54 | 55 | /////////////////////////////////////////////////////////////////////////////// 56 | // sequence_equal_byref_c 57 | inline bool sequence_equal_byref_c( foreach_const_container_type & rng, char const * result ) 58 | { 59 | BOOST_FOREACH( foreach_const_reference_type i, rng ) 60 | { 61 | if(0 == *result || i != *result) 62 | return false; 63 | ++result; 64 | } 65 | return 0 == *result; 66 | } 67 | 68 | /////////////////////////////////////////////////////////////////////////////// 69 | // mutate_foreach_byref 70 | // 71 | inline void mutate_foreach_byref( foreach_container_type & rng ) 72 | { 73 | BOOST_FOREACH( foreach_reference_type i, rng ) 74 | { 75 | ++i; 76 | } 77 | } 78 | 79 | 80 | /////////////////////////////////////////////////////////////////////////////// 81 | // sequence_equal_byval_n_r 82 | inline bool sequence_equal_byval_n_r( foreach_container_type & rng, char const * result ) 83 | { 84 | BOOST_REVERSE_FOREACH( foreach_value_type i, rng ) 85 | { 86 | if(0 == *result || i != *result) 87 | return false; 88 | ++result; 89 | } 90 | return 0 == *result; 91 | } 92 | 93 | /////////////////////////////////////////////////////////////////////////////// 94 | // sequence_equal_byval_c_r 95 | inline bool sequence_equal_byval_c_r( foreach_const_container_type & rng, char const * result ) 96 | { 97 | BOOST_REVERSE_FOREACH( foreach_value_type i, rng ) 98 | { 99 | if(0 == *result || i != *result) 100 | return false; 101 | ++result; 102 | } 103 | return 0 == *result; 104 | } 105 | 106 | /////////////////////////////////////////////////////////////////////////////// 107 | // sequence_equal_byref_n_r 108 | inline bool sequence_equal_byref_n_r( foreach_container_type & rng, char const * result ) 109 | { 110 | BOOST_REVERSE_FOREACH( foreach_reference_type i, rng ) 111 | { 112 | if(0 == *result || i != *result) 113 | return false; 114 | ++result; 115 | } 116 | return 0 == *result; 117 | } 118 | 119 | /////////////////////////////////////////////////////////////////////////////// 120 | // sequence_equal_byref_c_r 121 | inline bool sequence_equal_byref_c_r( foreach_const_container_type & rng, char const * result ) 122 | { 123 | BOOST_REVERSE_FOREACH( foreach_const_reference_type i, rng ) 124 | { 125 | if(0 == *result || i != *result) 126 | return false; 127 | ++result; 128 | } 129 | return 0 == *result; 130 | } 131 | 132 | /////////////////////////////////////////////////////////////////////////////// 133 | // mutate_foreach_byref 134 | // 135 | inline void mutate_foreach_byref_r( foreach_container_type & rng ) 136 | { 137 | BOOST_REVERSE_FOREACH( foreach_reference_type i, rng ) 138 | { 139 | ++i; 140 | } 141 | } 142 | 143 | #endif 144 | --------------------------------------------------------------------------------