New Standard Library Algorithms

Last updated Jan 1, 2003.

I promised not so long ago to present some of the brand new C++09 algorithms. All of the newly added algorithms have been available for years as nonstandard extensions. Now at last they are officially incorporated into the C++09 Committee Draft so there's no need to look for third-party libraries or roll your own.

Additional Versions of copy()

The copy() family of algorithms takes three arguments: two iterators indicating the beginning and the end of a range, and a single output iterator to determine the start of the output range. Sometimes however, it's more convenient to describe the operation as a starting point and a count instead of using a starting point and an ending point. The new copy_n() family of algorithms copy a known number of elements. For example, the following call copies n elements to res with first as the staring point:

copy_n(first, n res);

A counting version of uninitialized_copy() called uninitialized_copy_n() is now available. For example, the following call

uninitialized_copy_n(first, n, res);

invokes uninitialized_copy() for n elements.

copy_if() is another new C++09 algorithm. Technically speaking, copy_if() is redundant because it's the inverse of remove_copy_if(): copying all elements that satisfy a predicate p is just the same as not copying all elements that satisfy !p. However, it's more convenient and less confusing to use copy_if() directly. In the following example, copy_if() copies into res every element in range [first, last) which satisfies the predicate pred:

copy_if( first, last, res, pred);

Iota

This algorithm is inspired by an APL operator which is the Greek letter iota. The new iota() algorithm, which is my favorite C++09 algorithm, creates a range of sequentially increasing values. It's especially useful for testing and populating sequences of serial numbers. In the following example, the array a is filled with {0,1,2,3,4} using iota():

int a[4];
int val=0;
iota(a, a+4, val);

Formally, iota() works like this: for each element referred to by the iterator iter in the range [first, last), iota() assigns *iter = value and then increments value as if by ++value. For this to work, the third argument must meet the CopyConstructible and Assignable requirement. In addition, it has to be convertible to the type of *iter.

all_of(), any_of(), none_of()

These three algorithms provide set theory mathematical operations. Given a range and a predicate, the algorithm determines whether that predicate is true for all elements (all_of()); whether there exists an element for which the predicate is true (any_of()); or whether there exist no elements for which the predicate is true (none_of()). Technically, there was no need to provide all three of these algorithms (!none_of() and any_of() are equivalent), but all three of these operations are equally fundamental so the standards committee decided to define all three. With respect to their names, these algorithms have had various names over the years: all(), any() and none() are the more familiar names. However, to avoid name conflicts with nonstandard algorithms (and of course, with the std::tr1::any container-like class) the C++0x Committee Draft names these algorithms all_of(), any_of() and none_of(). The following examples demonstrate what these algorithms do:

all_of(first, last, is_positive);

returns true if all elements in the range [first,last) satisfy the is_poitive predicate.

any_of(first, last, is_positive);

returns true if any element in the range [first,last) satisfies the is_poitive predicate.

none_of(first, last, is_positive);

returns true if no element in the range [first,last) satisfies the is_poitive predicate.

Partition Algorithms

The standard already provides is_heap() and is_sorted() to test whether a range has a certain structure. The new predicate is_partitioned() returns true if a given range is partitioned. For example

int a[4]={-2,-1,0,1};
is_partitioned(a, a+4, is_negative);

returns true because all elements that satisfy is_negative appear before those that don't. Similarly, to detect the partition point in a partitioned range, the new algorithm partition_point() is now available:

int first_positive=*(partition_point(a, a+4, is_negtaive));

That is, partition_point() returns an iterator to the first element that doesn't satisfy the predicate is_negative.

You can read more about the new C++09 algorithm in Matt Austern's paper.