Boost Iterable Range LibraryWelcome to the home of Boost Iterable Range Library, which provides information about the Iterable Range concept (there are three Range concepts: Notional Range, Iterable Range and Indirect Range; for more details, see RangeLib). The Range concept is the result of a collaboration between John Torjo and Matthew Wilson, both frustrated by limitations in the STL Iterator concept. Among their other incarnations, John and Matthew are contributing editors to C/C++ Users Journal, in which the Range concept has been documented in recent articles. ContentsAn Iterable Range is a smarter pair of iterators (begin and end). It allows manipulation of both iterators (begin and end), and preserves the underlying iterator type (for example, if the underlying iterators are bidirectional, so will the range be). The fact that an iterable range holds two iterators (representing its position and its end position) makes it easier to:
Basic usageAll of the Iterable Range definitions and operations follow modern techniques. They all reside in the boost::rangelib namespace. When you construct a range, you either construct it from a container, or a pair of iterators. When you know the container type, use crange: typedef std::vector<int> array; array a; crange<array> r(a); // non-const range crange<const array> const_r(a); // const range Whe you know only the iterator type, use irange: template<class iterator> void print_range(iterator begin, iterator end) { for ( irange<iterator> r(begin,end); r; ++r) std::cout << *r << std::endl; } Range algorithmsBecause the fact that an Iterable Range contains two iterators is a prerequisite, adapting all STL algorithms to work for Iterable Ranges is quite simple. In order to use an STL algorithm adapted for Iterable Range, just use the rng:: prefix instead of std:: std::vector<int> v; std::list<int> l; // print vector rng::copy(v, std::ostream_iterator<int>(std::cout," ")); // copy vector to list rng::copy(v, std::back_inserter(l)); Range CompositionOne of the most powerful features of the Iterable Range concept is "Range Composition". You can take one range as input, and yield another one as output (which you usually use in algorithms). The simplest example is filtering - you can filter an existing range and/or container. bool is_even(int i){ return (i % 2) == 0; } ... std::list The result of one composition can be the input for another composition. For instance, you can print the squared of each even number: // ... same as above int square(int n) { return n * n } rng::copy(transformed(filtered(l,&is_even),&sqare), std::ostream_iterator<int>(...)); In order for range composition to work, we have provided the following range adaptors. Range AdaptorsA range adaptor is a function that adapts an iterator in order to be used within an Iterable Range as simple as possible. Consided the filtered example above. Had we not used an adaptor, we should have done something similar to: typedef boost::filter_iterator<std::list<int>::iterator> iterator; irange<iterator> r( iterator(l.begin(),&is_even), iterator(l.end(),&is_even) ); rng::copy( r, std::ostream_iterator<int>(...) ); Of course, in client code, and especially in generic code, this can become a maintenance nightmare (also, note that in real code, you won't use names like 'l', so the hush-mush code will get even worse). And what about when you want to do a double-composition (like the transformed filtered range example above)? It could become close to impossible to get it right the first time. Thus, range adaptors fill this gap. Here's what we've already provided:
Finally, note that when you download the code, there are examples for each of the above adaptors. Related PublicationsArticles
Books
|
|