tags:

views:

295

answers:

3

I was wondering if there is an iterator in the STL that dereferences the object pointed before returning it. This could be very useful when manipulating containers aggregating pointers. Here's an example of what I would like to be able to do:

#include <vector>
#include <iterator>
#include <algorithm>

using namespace std;

int main()
{
  vector<int*> vec;

  int i = 1;
  int j = 2;
  int k = 3;

  vec.push_back(&i);
  vec.push_back(&j);
  vec.push_back(&k);

  copy(deref_iterator(vec.begin()), 
       deref_iterator(vec.end()), 
       ostream_iterator<int>(cout, " ")); // prints "1 2 3"

  return 0;
}
+2  A: 

If it is impossible using Boost, writing a custom iterator is not that hard. Here is an example of a "dereference iterator" that meets the InputIterator requirements :

#include <iterator>

template <typename T>
struct PointedType;

template <typename T>
struct PointedType<T*>
{
  typedef T value_type;
};

template <typename InputIterator>
struct DerefIterator
{
  typedef input_iterator_tag iterator_category;
  typedef typename PointedType<
            typename iterator_traits<InputIterator>::value_type>::value_type
            value_type;
  typedef typename iterator_traits<InputIterator>::difference_type
            difference_type;
  typedef value_type* pointer;
  typedef value_type& reference;

  public:
    explicit DerefIterator(const InputIterator& ii)
      : it(ii) {}

    // Returns the object pointed by the object referenced by it
    reference operator*()  const { return **it; }
    pointer   operator->() const { return *it; }

    DerefIterator& operator++()
    {
        ++it;
        return *this;
    }

    DerefIterator operator++(int)
    {
        DerefIterator tmp = *this;
        ++it;
        return tmp;
    }

    bool equals(const DerefIterator<InputIterator> & di) const
    {
        return di.it == it;
    }

  private:
    InputIterator it;
};

// Equality functions

template <typename InputIterator>
inline bool operator==(const DerefIterator<InputIterator>& di1, 
                       const DerefIterator<InputIterator>& di2)
{
  return di1.equals(di2);
}

template <typename InputIterator>
inline bool operator!=(const DerefIterator<InputIterator>& di1, 
                       const DerefIterator<InputIterator>& di2)
{
  return ! (di1 == di2);
}

//Helper function

template <typename InputIterator>
DerefIterator<InputIterator> deref_iterator(const InputIterator& ii)
{
  return DerefIterator<InputIterator>(ii);
}
Luc Touraille
+9  A: 

Try Boost's indirect_iterator.

An indirect_iterator has the same category as the iterator it is wrapping. For example, an indirect_iterator<int**> is a random access iterator.

James Hopkin
Exactly what I was asking for. Shame on me for not thinking about Boost :-)! However, I would have expected such an iterator to be present in the standard library...
Luc Touraille
+3  A: 

Assuming your actual use case is a bit more complex than a container of integer pointers!

You could check out the boost ptr containers
http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/reference.html

The containers contain dynamically allocated objects (ie pointers).
But all access to the objects (direct or via iterator) returns a reference to the object.

#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

int main()
{
  boost::ptr_vector<int> vec;

  vec.push_back(new int(1));
  vec.push_back(new int(2));
  vec.push_back(new int(3));

  copy(vec.begin(),vec.end(),
       ostream_iterator<int>(std::cout, " ")); // prints "1 2 3 "

  return 0;
}
Martin York
Well, this is fine if you want the container to have the ownership of the elements. indirect_iterator seems more appropriate when dealing with pointers to object with entity semantic which are already owned by something else (or allocated on the stack).
Luc Touraille