All,
I've been using the boost range library for a few months now, and it's
simplified my life considerably.
I occasionally want to use something akin to MPL's zip_view and
unpack_args with my ranges. For example:
<code>
const std::vector<int> vec1 = list_of(1)(2)(3)(4)(5)(6);
std::vector<int> vec2 = list_of(10)(20)(30)(40)(50)(60);
std::vector<int> vec3 = list_of(100)(200)(300)(400)(500)(600);
boost::for_each(zip(vec1, vec2, vec3) | strided(2), unpack(
std::cout << px::val('(') << arg1 <<", "<< arg2 <<", "<< arg3 << ")\n"));
boost::transform(vec1, boost::begin(zip(vec3, vec2)),
px::construct
All,
Wanted to ping on this again.
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. For example: <snip code> I may have missed it in the documentation or on the list, but I haven't found anything like that. Does anyone know of such an adaptor?
Looking around it appears that fusion::invoke may do what I'd like for the unpack_args equivalent. The zip/unpack has been useful enough that I've created a version using Boost.PP to generate all needed versions of user-specified arities (default of 5). If I don't hear back I'll probably post a proposal to the main boost list (and then I'll take any silence to indicate a lack of interest ;). Thanks, Nate
On 01/26/2011 11:26 PM, Nathan Crookston wrote:
All,
Wanted to ping on this again.
I occasionally want to use something akin to MPL's zip_view and unpack_args with my ranges. For example: <snip code> I may have missed it in the documentation or on the list, but I haven't found anything like that. Does anyone know of such an adaptor? Looking around it appears that fusion::invoke may do what I'd like for
On Sat, Jan 22, 2011 at 4:21 PM, Nathan Crookston
wrote: the unpack_args equivalent. The zip/unpack has been useful enough that I've created a version using Boost.PP to generate all needed versions of user-specified arities (default of 5). More details?
Patrick
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
2011/1/28 Nathan Crookston
[...]
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.)
I'm with you. IMHO, that's something missed in Boost.Range. boost::for_each(zip(images, offsets) | strided(2),
unzip(AddToMosaic(mosaic))); [...] The unpack() function would be useful for the zip_iterator as well.
Is Fusion's make_fused() the equivalent?
On Thu, Jan 27, 2011 at 1:04 PM, TONGARI
boost::for_each(zip(images, offsets) | strided(2), unzip(AddToMosaic(mosaic))); [...] The unpack() function would be useful for the zip_iterator as well.
Is Fusion's make_fused() the equivalent?
Yes, I replaced all my uses of unpack with make_fused and everything looks like it's working. Thanks for pointing it out. If the range authors are interested I'll probably post my code with unpack (which depends only on boost::result_of) and let them make the call whether they want to introduce a fusion dependency. This does raise a naming question. MPL uses unpack_args, Fusion uses make_fused. I thought unpack was nice (I also like unzip), but I'm not dead-set on any particular name. Any thoughts? Thanks, Nate
On Thu, Jan 27, 2011 at 9:48 PM, Nathan Crookston < nathan.crookston@gmail.com> wrote:
On Thu, Jan 27, 2011 at 1:04 PM, TONGARI
wrote: boost::for_each(zip(images, offsets) | strided(2), unzip(AddToMosaic(mosaic))); [...] The unpack() function would be useful for the zip_iterator as well.
Is Fusion's make_fused() the equivalent?
Yes, I replaced all my uses of unpack with make_fused and everything looks like it's working. Thanks for pointing it out. If the range authors are interested I'll probably post my code with unpack (which depends only on boost::result_of) and let them make the call whether they want to introduce a fusion dependency.
I will provide a zipped Range Adaptor that does not introduce a dependency on Fusion. I will target Boost 1.47 for this feature. Now that the Range Adaptor framework is well proven it makes sense to build upon it by broadening the Range Adaptor facilities. The zipped adaptor is one of the most frequently requested, and is top of my list.
This does raise a naming question. MPL uses unpack_args, Fusion uses make_fused. I thought unpack was nice (I also like unzip), but I'm not dead-set on any particular name. Any thoughts?
My thoughts on this at the moment are that I will use the MPL names. I will probably use directly MPL.
Thanks, Nate
Regards, Neil Groves
Hi Neil,
On Thu, Jan 27, 2011 at 3:37 PM, Neil Groves
I will provide a zipped Range Adaptor that does not introduce a dependency on Fusion. I will target Boost 1.47 for this feature. Now that the Range Adaptor framework is well proven it makes sense to build upon it by broadening the Range Adaptor facilities. The zipped adaptor is one of the most frequently requested, and is top of my list.
This is great news! Thanks for letting me know.
This does raise a naming question. MPL uses unpack_args, Fusion uses make_fused. I thought unpack was nice (I also like unzip), but I'm not dead-set on any particular name. Any thoughts?
My thoughts on this at the moment are that I will use the MPL names. I will probably use directly MPL.
This sounds reasonable to me -- although explicitly calling a range adaptor a view seems redundant. Perhaps zip and unpack_args? I'm attaching my code which supplies the (not renamed) zip and unpack functions. I've tested it on windows with g++3, g++4 (with and without -std=c++0x), VC8 and VC10. The maximum number of arguments that may be supplied to zip are controllable by BOOST_RANGE_MAX_ZIP_ARGUMENTS (defaults to 5). Perhaps you'll find it useful -- correctly handing rvalues without rvalue references available was tricky. Thanks, Nate
participants (4)
-
Nathan Crookston
-
Neil Groves
-
Patrick Horgan
-
TONGARI