Hi Patrick,
On Thu, Jan 27, 2011 at 1:53 AM, Patrick Horgan
On Sat, Jan 22, 2011 at 4:21 PM, Nathan Crookston
I occasionally want to use something akin to MPL's zip_view and unpack_args with my ranges More details?
Fair enough -- I'll try to give some brief motivation and examples:
I often find that I have ranges whose elements are related to each
other. For example, I may have a list of images and a list of
offsets:
//Assume 0th elements of images and offsets are related, and so forth.
vector<Image> images(...);
vector<Offset> offsets(...);
If I wish to create a mosaic by adding each image/offset pair to an
aggregate image I currently have a few options:
//First option -- iterators for both. Requires an awful lot of
typing, introduces
// a new variable outside the for-loop scope. Code using an index is
much more concise,
// but both suffer from the problem of not being composable (more on
that later).
Mosaic mosaic;
vector<Offset>::iterator j = offsets.begin()
for(vector<Image>::iterator i = images.begin(); i != images.end() && j
!= offsets.end(); ++i, ++j)
mosaic.add(*i, *j);
//Second option -- create a zip_iterator [1]. This obviously requires
a lot more typing.
// I think this is moving in the right direction.
for_each(boost::make_zip_iterator(boost::make_tuple(images.begin(),
offsets.begin())),
boost::make_zip_iterator(boost::make_tuple(images.end(),
offsets.end())),
AddToMosaic(mosaic));
I decided to create a new range adaptor based the zip_iterator which
reduces the verbosity of the loop declaration. Such an adaptor is
common for this problem [2][3]. I was surprised that I couldn't find
this already in the range library. (Feel free to disabuse me if
necessary.)
//Using the zip range adaptor. Creates begin and end zip_iterators
under the hood.
boost::for_each(zip(images, offsets), AddToMosaic(mosaic));
The previous looks much nicer and more expressive to my eye. Note
that we're not copying any elements -- it's a lazy adaptor, like the
other range adaptors. It's also composable:
//Passes elements 0,2,4, etc. packed into a tuple of references.
boost::for_each(zip(images, offsets) | strided(2), AddToMosaic(mosaic));
My implementation of zip supports multiple arguments (controlled by a
preprocessor symbol, currently 5). Hopefully my reasons for
suggesting zip are clear.
I also wrote a function corresponding to mpl::unpack_args. If we
examine the declaration of AddToMosaic it's clear that using zip() is
still burdening us with syntax contortions:
struct AddToMosaic
{
AddToMosaic(Mosaic& rMosaic) : m_rMosaic(rMosaic) {}
void operator()(const boost::tuple