The Boost C++ Libraries

Helper Classes and Functions

The algorithms and adaptors provided by Boost.Range are based on templates. You don’t have to transform a container to a range to pass it to an algorithm or adaptor. However, Boost.Range defines a few range classes, with boost::iterator_range being the most important. boost::iterator_range is required because adaptors and a few algorithms return ranges that must have a type. In addition, helper functions exist that create ranges whose iterators contain all the data required for an iteration. The iterators from these ranges don’t refer to a container or to another data structure. A class like boost::iterator_range is used here, too.

Example 30.7. Creating a range for integers with boost::irange()
#include <boost/range/algorithm.hpp>
#include <boost/range/irange.hpp>
#include <iostream>

int main()
{
  boost::integer_range<int> ir = boost::irange(0, 3);
  boost::copy(ir, std::ostream_iterator<int>{std::cout, ","});
}

Example 30.7 uses the function boost::irange(). This function creates a range for integers without having to use a container or another data structure. You only pass a lower and upper bound to boost::irange() with the upper bound being exclusive.

boost::irange() returns a range of type boost::integer_range. This class is derived from boost::iterator_range. boost::iterator_range is a template that expects an iterator type as its sole template parameter. The iterator used by boost::irange() is tightly coupled to that function and is an implementation detail. Thus, the iterator type isn’t known and can’t be passed as a template parameter to boost::iterator_range. However, boost::integer_range only expects an integer type, which makes it easier to use than if you had to pass an iterator type.

Example 30.7 writes 0,1,2 to standard output.

Example 30.8. Creating a range for an input stream with boost::istream_range()
#include <boost/range/algorithm.hpp>
#include <boost/range/istream_range.hpp>
#include <iterator>
#include <iostream>

int main()
{
  boost::iterator_range<std::istream_iterator<int>> ir =
    boost::istream_range<int>(std::cin);
  boost::copy(ir, std::ostream_iterator<int>{std::cout, "\n"});
}

Example 30.8 introduces the function boost::istream_range(), which creates a range for an input stream. The function returns the range as a boost::iterator_range. This means that an iterator type has to be passed as a template parameter.

When you start Example 30.8, type a number, and press Enter, the number is printed in the next line. If you type another number and press Enter, that number is printed. The range returned by boost::istream_range() makes it possible for boost::copy() to iterate over all entered numbers and write them to std::cout.

You can terminate the program any time by typing Ctrl+C.

Besides boost::iterator_range, Boost.Range provides the class boost::sub_range, which is derived from boost::iterator_range. boost::sub_range is a template like boost::iterator_range. However, boost::sub_range expects the type of the range as a template parameter, not an iterator type. This can simplify usage.

Example 30.9. Creating ranges more easily with boost::sub_range()
#include <boost/range/algorithm.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/sub_range.hpp>
#include <array>
#include <iterator>
#include <iostream>

int main()
{
  std::array<int, 6> a{{0, 1, 2, 3, 4, 5}};
  boost::iterator_range<std::array<int, 6>::iterator> r1 =
    boost::random_shuffle(a);
  boost::sub_range<std::array<int, 6>> r2 =
    boost::random_shuffle(r1);
  boost::copy(r2, std::ostream_iterator<int>{std::cout, ","});
}

A few algorithms from Boost.Range return a range – for example, boost::random_shuffle(). This algorithm directly modifies the range passed to it by reference and returns the modified range. In Example 30.9, boost::random_shuffle() is called twice, so array a is randomly shuffled twice.

For the first return value, the example uses boost::iterator_range; for the second return value, it uses boost::sub_range. The usage of both classes only differs in the template parameter. Not only can boost::sub_range be instantiated more easily, but it also provides the type definition const_iterator.