3

Let's say I want to write a simple function keys that takes in a std::map and returns an iterator_range that provides the keys of the map. How would I do it?

template<typename A, typename B>
Range<A> keys(const std::map<A, B> & m) { ??? }

I want to apply the same pattern to various other containers, but I think this is a good prototypical example.

Edit: I'm guessing I need something in the realm of Boost's range_adapters and/or transform_iterators but I'm not familiar enough with them to apply them here.

Elliot Cameron
  • 5,235
  • 2
  • 27
  • 34
  • Are you talking about [boost's `iterator_range`](http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/utilities/iterator_range.html)? – dyp Jan 25 '14 at 23:07
  • Yes, but I'm not attached to it. – Elliot Cameron Jan 25 '14 at 23:10
  • 1
    .... something like the [`boost::adaptors::keys`](http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/map_keys.html) function? – dyp Jan 25 '14 at 23:34
  • @dyp: The best things in life have already been done. ;) Thanks. I'll have to look at the implementation and see if that helps me repeat the pattern elsewhere. – Elliot Cameron Jan 25 '14 at 23:43
  • @3noch - have you find a solution? if yes, answer your own question so the community will learn – NirMH Jun 01 '14 at 08:04

1 Answers1

1

This particular need is met with boost::adapters::keys. More generally, boost::range allows you to design your own adapters, but it's somewhat involved. So unless you're designing a new library, you might be able to get away with transformed.

If you need the result of your range back into a container, you can write a simple collect function which will "collect" the result of a boost::range pipeline.

template<typename Output, typename SinglePassRange>
Output collect(const SinglePassRange & rng)
{
    Output r;
    boost::range::copy(rng, std::inserter(r, boost::begin(r)));
    return r;
}

Now you can easily whip up some little functions and

  • collect<vector<int>>(numbers | filtered(odd))
  • collect<vector<int>>(numbers | transformed(doubled))
  • collect<vector<K>>(myMap | transformed(keyOf))
Elliot Cameron
  • 5,235
  • 2
  • 27
  • 34