2008-12-09 3 views
14

Мне было интересно, есть ли итератор в STL, который разделяет объект, указанный перед его возвратом. Это может быть очень полезно при манипулировании контейнерами, агрегирующими указатели. Вот пример того, что я хотел бы быть в состоянии сделать:Есть ли в 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; 
} 

ответ

11

Try подталкивания-х indirect_iterator.

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

+0

То, что я просил. Позор мне не задумываться о Boost :-)! Однако я бы ожидал, что такой итератор будет присутствовать в стандартной библиотеке ... – 2008-12-09 10:54:59

4

Если это невозможно, используя подталкивание, написание пользовательского итератора не так уж трудно. Вот пример «разыменования итератора», который отвечает требованиям 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); 
} 
+0

Вы должны использовать 'using namespace std;' для вышеприведенного для компиляции. – 2012-01-02 15:44:58

+0

@ DavidDoria: лучший подход - это префикс `input_iterator_tag` и` iterator_traits` с префиксом `std`. – 2012-01-03 08:16:26

4

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

Вы можете проверить подталкивание 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; 
} 
Смежные вопросы