Есть ли dereference_iterator в STL? - PullRequest
15 голосов
/ 09 декабря 2008

Мне было интересно, есть ли в STL итератор, который разыменовывает объект, на который указывает объект, прежде чем его вернуть. Это может быть очень полезно при манипулировании указателями в контейнерах. Вот пример того, что я хотел бы сделать:

#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;
}

Ответы [ 3 ]

11 голосов
/ 09 декабря 2008

Попробуйте Boost's indirect_iterator.

indirect_iterator имеет ту же категорию, что и итератор, с которым он переносит. Например, indirect_iterator<int**> является итератором произвольного доступа.

4 голосов
/ 09 декабря 2008

Предположим, что ваш фактический вариант использования немного сложнее, чем контейнер целочисленных указателей!

Вы можете проверить надстройку ptr-контейнеров
http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/reference.html

Контейнеры содержат динамически размещаемые объекты (например, указатели).
Но весь доступ к объектам (прямой или через итератор) возвращает ссылку на объект.

#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;
}
4 голосов
/ 09 декабря 2008

Если невозможно использовать Boost, написать собственный итератор не так сложно. Вот пример «итератора разыменования», который отвечает требованиям InputIterator:

#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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...