foreach.qbk
来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 519 行 · 第 1/2 页
QBK
519 行
[library Boost.Foreach [quickbook 1.3] [authors [Niebler, Eric]] [copyright 2004 Eric Niebler] [category algorithms] [purpose foreach looping construct, for writing simple loops over STL containers, null-terminated strings, arrays, iterator pairs and user defined types. ] [id foreach] [dirname foreach] [license Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at [@http://www.boost.org/LICENSE_1_0.txt]) ]][/ Images ][def _note_ [$images/note.png]][def _alert_ [$images/caution.png]][def _detail_ [$images/note.png]][def _tip_ [$images/tip.png]][/ Links ][def _foreach_ [^BOOST_FOREACH]] [def _range_ [@../../libs/range/index.html Boost.Range]][def _iterator_range_ [@../../libs/range/doc/utility_class.html#iter_range `boost::iterator_range<>`]][def _sub_range_ [@../../libs/range/doc/utility_class.html#sub_range `boost::sub_range<>`]][def _extending_range_ [@../../libs/range/doc/boost_range.html#minimal_interface Extending Boost.Range]][def _single_pass_range_concept_ [@../../libs/range/doc/range.html#single_pass_range Single Pass Range Concept]][def _range_portability_ [@../../libs/range/doc/portability.html Boost.Range Portability]][def _noncopyable_ [@../../libs/utility/utility.htm#Class_noncopyable `boost::noncopyable`]][def _iterator_ [@../../libs/iterator/doc/index.html Boost.Iterator]][section Introduction][:["Make simple things easy.]\n[*['-- Larry Wall]]][h2 What is _foreach_?]In C++, writing a loop that iterates over a sequence is tedious. We can eitheruse iterators, which requires a considerable amount of boiler-plate, or we canuse the `std::for_each()` algorithm and move our loop body into a predicate, whichrequires no less boiler-plate and forces us to move our logic far from whereit will be used. In contrast, some other languages, like Perl, provide a dedicated"foreach" construct that automates this process. _foreach_ is just such a constructfor C++. It iterates over sequences for us, freeing us from having to deal directlywith iterators or write predicates._foreach_ is designed for ease-of-use and efficiency. It does no dynamic allocations,makes no virtual function calls or calls through function pointers, and makes no callsthat are not transparent to the compiler's optimizer. This results in near-optimal codegeneration; the performance of _foreach_ is usually within a few percent of theequivalent hand-coded loop. And although _foreach_ is a macro, it is a remarkablywell-behaved one. It evaluates its arguments exactly once, leading to no nasty surprises.[h2 Hello, world!]Below is a sample program that uses _foreach_ to loop over the contents ofa `std::string`. #include <string> #include <iostream> #include <boost/foreach.hpp> int main() { std::string hello( "Hello, world!" ); BOOST_FOREACH( char ch, hello ) { std::cout << ch; } return 0; }This program outputs the following:[preHello, world!][h2 Supported Sequence Types]_foreach_ iterates over sequences. But what qualifies as a sequence, exactly? Since_foreach_ is built on top of _range_, it automatically supports those types which_range_ recognizes as sequences. Specifically, _foreach_ works with types that satisfythe _single_pass_range_concept_. For example, we can use _foreach_ with:* STL containers* arrays* Null-terminated strings (`char` and `wchar_t`)* std::pair of iterators[note The support for STL containers is very general; anything that looks likean STL container counts. If it has nested `iterator` and `const_iterator` types and `begin()`and `end()` member functions, _foreach_ will automatically know how to iterate overit. It is in this way that _iterator_range_ and _sub_range_ work with _foreach_.]See the section on [link foreach.extensibility Extensibility] to findout how to make _foreach_ work with other types.[h2 Examples]Below are some examples that demonstrate all the different ways we can use _foreach_.Iterate over an STL container: std::list<int> list_int( /*...*/ ); BOOST_FOREACH( int i, list_int ) { // do something with i }Iterate over an array, with covariance (i.e., the type of the iteration variable isnot exactly the same as the element type of the container): short array_short[] = {1,2,3}; BOOST_FOREACH( int i, array_short ) { // The short was implicitly converted to an int }Predeclare the loop variable, and use `break`, `continue`, and `return` in the loop body: std::deque<int> deque_int( /*...*/ ); int i = 0; BOOST_FOREACH( i, deque_int ) { if( i == 0 ) return; if( i == 1 ) continue; if( i == 2 ) break; }Iterate over a sequence by reference, and modify the underlying sequence: short array_short[] = { 1, 2, 3 }; BOOST_FOREACH( short & i, array_short ) { ++i; } // array_short contains {2,3,4} hereIterate over a vector of vectors with nested _foreach_ loops. In thisexample, notice that braces around the loop body are not necessary: std::vector<std::vector<int> > matrix_int; BOOST_FOREACH( std::vector<int> & row, matrix_int ) BOOST_FOREACH( int & i, row ) ++i;Iterate over an expression that returns a sequence by value (i.e. an rvalue): extern std::vector<float> get_vector_float(); BOOST_FOREACH( float f, get_vector_float() ) { // Note: get_vector_float() will be called exactly once } Iterate in reverse: std::list<int> list_int( /*...*/ ); BOOST_REVERSE_FOREACH( int i, list_int ) { // do something with i }Iterating over rvalues doesn't work on some older compilers. Check the [link foreach.portability Portability] section to see whether yourcompiler supports this.[h2 Making _foreach_ Prettier]People have complained about the name _foreach_. It's too long. `ALL CAPS` canget tiresome to look at. That may be true, but _foreach_ is merely followingthe [@http://www.boost.org/more/lib_guide.htm Boost Naming Convention]. Thatdoesn't mean you're stuck with it, though. If you would like to use a differentidentifier (`foreach`, perhaps), you can simply do: #define foreach BOOST_FOREACH #define reverse_foreach BOOST_REVERSE_FOREACHOnly do this if you are sure that the identifier you choose will not causename conflicts in your code.[note Do not use `#define foreach(x,y) BOOST_FOREACH(x,y)`. This can be problematic if the arguments are macros themselves. This would result in an additional expansion of these macros. Instead, use the form shown above.][endsect][section Extensibility]If we want to use _foreach_ to iterate over some new collection type, we must"teach" _foreach_ how to interact with our type. Since _foreach_ is built on topof _range_, we must extend _range_ in order to extend _foreach_. The section_extending_range_ explores this topic in detail.Below is an example for extending _foreach_ to iterate over a sub-string type,which contains two iterators into a `std::string`. namespace my { // sub_string: part of a string, as delimited by a pair // of iterators struct sub_string { std::string::iterator begin; std::string::iterator end; /* ... implementation ... */ }; // Add overloads of range_begin() and range_end() in the // same namespace as sub_string, to be found by Argument-Dependent Lookup. inline std::string::iterator range_begin( sub_string & x ) { return x.begin; } inline std::string::iterator range_end( sub_string & x ) { return x.end; } // Also add overloads for const sub_strings. Note we use the conversion // from string::iterator to string::const_iterator here. inline std::string::const_iterator range_begin( sub_string const & x ) { return x.begin; } inline std::string::const_iterator range_end( sub_string const & x ) { return x.end; } } namespace boost { // specialize range_mutable_iterator and range_const_iterator in namespace boost template<> struct range_mutable_iterator< my::sub_string > { typedef std::string::iterator type; }; template<> struct range_const_iterator< my::sub_string > { typedef std::string::const_iterator type; };
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?