Boost logo

Boost Users :

Subject: Re: [Boost-users] Iterating over the seconds of a list of pairs
From: Björn Karlsson (Bjorn.Karlsson_at_[hidden])
Date: 2009-08-17 15:01:16


Hello Hicham,

> I have a similar problem. I have a vector< pair<LeftT, RightT> >.
> I'm very happy to use vector< pair<LeftT, RightT> >::iterator
>
> The only extra is I'd like to name the functions GetLeft() and
> GetRight()
> and make them callable as:
>
> typedef vector< pair<LeftT, RightT> >::iterator stl_iterator;
> stl_iterator i = ...;
> i->GetLeft() and i->GetRight() // I can't do this obviously

You could inherit from std::pair and add the member functions GetLeft() and GetRight() to your derived class. Or implement your pair from scratch, naming the members according to your domain.
 
> so:
> typedef boost::transform_iterator<functor, stl_iterator>
> my_iterator_type;
>
> Should functor provide GetLeft() and GetRight()?
> or should my_iterator_type derive from the result of
> transform_iterator<functor, stl_iterator> ?

It's technically possible to use transform_iterator for what you want, but it's much too complicated for just the convenience of those two additional member functions. Free functions would be cleaner, easier, and almost as convenient for your users:

template <typename T, typename U> T& GetLeft(std::pair<T,U>& p) {
  return p.first;
}

template <typename T, typename U> const T& GetLeft(const std::pair<T,U>& p) {
  return p.first;
}

With that, you can write code like:

  iterator it = container.begin();
  GetLeft(*it);

If you really, really, really want to go through the trouble of adding GetLeft() and GetRight() using transform_iterator, you can do this:

1) Write a class that stores a reference to a pair and implements GetLeft() and GetRight() to return pair::first and pair::second, respectively.
2) Write a function object that returns an instance of the class from 1) in the function call operator (taking one argument that is a reference to a pair). The function call operator need to be declared const, and you'll need a typedef for result_type that is the class from 1).
3) Use the function object in 2) as the unary function for transform_iterator.

But if you're willing to go through all of that trouble it's much better to go with the derived class -- less work, probably more efficient, and definitely more maintainable. I only mention the above because there might be other use cases (such as when implementing the Adapter pattern) when it actually makes sense to do something like that. However, I have yet to see a real-world scenario for that. (Since I don't recommend the technique for this issue, I won't attach sample code...)

Does that help?

Cheers,
Bjorn Karlsson
www.skeletonsoftware.net


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net