BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_transformiterator

Detailed Description

Outline

Purpose

Provide a wrapping iterator that invokes a functor on dereference.

Classes

Description

This component implements a class template, bdlb::TransformIterator, that stores an underlying iterator and a one-argument functor. Iterator operations are passed through to the underlying iterator, with the exception of dereference. For dereference, the functor is invoked on the result of dereferencing the underlying iterator, and the result of the functor invocation is returned. This component also implements a utility class, bdlb::TransformIteratorUtil, that provides a function template for creating TransformIterator objects.

The templates expect two parameters. The first parameter, designated FUNCTOR, is the type of a callable object that can be invoked with a single argument. When compiling with C++03, this type must be either a function pointer or otherwise have a type from which bslmf::ResultType can determine the result type of invoking the functor (see bslmf_resulttype ). The second parameter, designated ITERATOR, is the type of an object that models an iterator from which values may be obtained, i.e., a type such that bsl::iterator_traits<ITERATOR> exists and for which typename bsl::iterator_traits<ITERATOR>::iterator_category derives from bsl::input_iterator_tag (see bslstl_iterator ). Note that object pointer types qualify.

Note that bdlb::TransformIterator is more useful in C++11 or later than in C++03, because lambdas can be used as function objects to match a FUNCTOR of type bsl::function<RETURN_TYPE(INPUT_TYPE)>.

Usage

This section illustrates intended use of this component.

Example 1: Totaling a Grocery List

Suppose we have a shopping list of products and we want to compute how much it will cost to buy selected items. We can use bdlb::TransformIterator to do the computation, looking up the price of each item.

First, we set up the price list:

prices["pudding"] = 1.25;
prices["apple"] = 0.33;
prices["milk"] = 2.50;
Definition bslstl_map.h:619

Then, we set up our shopping list:

list.push_back("milk");
list.push_back("milk");
list.push_back("pudding");
Forward declaration required by List_NodeProctor.
Definition bslstl_list.h:1033
void push_back(const value_type &value)
Definition bslstl_list.h:3020

Next, we create a functor that will return a price given a product. The following rather prolix functor at namespace scope is necessary for C++03:

#ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
class Pricer {
private:
// DATA
const bsl::map<bsl::string, double> *d_prices_p; // price list
public:
// PUBLIC TYPES
typedef double result_type;
// CREATORS
/// Create a `Pricer` object using the specified `prices`. The
/// lifetime of `prices` must be at least as long as this object.
explicit Pricer(const bsl::map<bsl::string, double> *prices);
// ACCESSORS
/// Return the price of the specified `product`.
double operator()(const bsl::string& product) const;
};
// CREATORS
Pricer::Pricer(const bsl::map<bsl::string, double> *prices)
: d_prices_p(prices)
{
}
double Pricer::operator()(const bsl::string& product) const
{
d_prices_p->find(product);
return i == d_prices_p->end() ? 0.0 : i->second;
}
#endif
Definition bslstl_string.h:1281
BloombergLP::bslstl::TreeIterator< const value_type, Node, difference_type > const_iterator
Definition bslstl_map.h:724
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_map.h:2759

Then, we create the functor object. In C++11 or later, the explicit functor class above is unnecessary since we can use a lambda:

#ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
Pricer pricer(&prices);
#else
auto pricer = [&](const bsl::string &product) { return prices[product]; };
#endif

Now, we need a pair of transform iterators to process our grocery list. We can use TransformIteratorUtil::make to create those iterators, avoiding the need to explicitly name types. We create the iterators and process the list in one step, as follows:

double total = bsl::accumulate(
0.0);
void swap(list &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocTraits const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_list.h:1829
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_list.h:2829
static TransformIterator< FUNCTOR, ITERATOR > make(const ITERATOR &iterator, const FUNCTOR &functor, bslma::Allocator *basicAllocator=0)
Definition bdlb_transformiterator.h:1067

Finally, we verify that we have the correct total:

assert(6.25 == total);

Example 2: Totaling the Grocery List Again

In the previous example, we did not explicitly name our iterator type. We may want to do so, however, if we intend to reuse iterators, or store them in data structures. We will rework the previous example using explicitly typed iterators. We also demonstrate how a single iterator type can deal with multiple functors.

First, we notice that we have two different functor types depending on whether we compile as C++03 or C++11. To abstract away the difference, we will use a bsl::function functor type that is conformable to both:

Definition bdlb_transformiterator.h:421
Definition bslstl_list.h:739
Forward declaration.
Definition bslstl_function.h:934

Then, we create a pair of these iterators to traverse our list:

Iterator groceryBegin(list.begin(), pricer);
Iterator groceryEnd(list.end(), pricer);

Now, we add up the prices of our groceries:

double retotal = bsl::accumulate(groceryBegin, groceryEnd, 0.0);

Finally, we verify that we have the correct total:

assert(6.25 == retotal);

Example 3: Summing Absolute Values

Suppose we have a sequence of numbers and we would like to sum their absolute values. We can use bdlb::TransformIterator for this purpose.

First, we set up the numbers:

int data[5] = { 1, -1, 2, -2, 3 };

Then, we need a functor that will return the absolute value of a number. Rather than write a functor object, we can use a simple pointer to function as a functor:

int (*abs)(int) = &bsl::abs;

Next, we create the transform iterators that will convert a number to its absolute value. We need iterators for both the beginning and end of the sequence:

bdlb::TransformIterator<int(*)(int), int *> dataBegin(data + 0, abs);
bdlb::TransformIterator<int(*)(int), int *> dataEnd (data + 5, abs);

Now, we compute the sum of the absolute values of the numbers:

int sum = bsl::accumulate(dataBegin, dataEnd, 0);

Finally, we verify that we have computed the sum correctly:

assert(9 == sum);