2008-12-09 11 views
14

Me preguntaba si hay un iterador en el STL que desreferencia el objeto apuntado antes de devolverlo. Esto podría ser muy útil al manipular contenedores que agregan punteros. He aquí un ejemplo de lo que me gustaría ser capaz de hacer:¿Hay un dereference_iterator en el 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; 
} 

Respuesta

11

Trate de indirect_iterator Boost.

Un indirect_iterator tiene la misma categoría que el iterador que está envolviendo. Por ejemplo, un indirect_iterator<int**> es un iterador de acceso aleatorio.

+0

Exactamente lo que estaba pidiendo. Lástima de mí por no pensar en Boost :-)! Sin embargo, esperaba que ese iterador estuviera presente en la biblioteca estándar ... –

+0

Bueno, ¿se puede resolver un problema más difícil? Quiero ordenar el vector de ptrs o particionarlo aplicando funciones desde . El problema aquí es que necesito intercambiar punteros en un contenedor, mientras que la desreferencia a los valores del objeto. – 0x2207

4

Si no es posible el uso de Boost, escribir un iterador personalizado no es tan difícil. Este es un ejemplo de un "iterador eliminar la referencia" que cumpla con los requisitos 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

Debe usar 'using namespace std;' para lo anterior para compilar. –

+0

@DavidDoria: Un mejor enfoque es prefijar 'input_iterator_tag' y' iterator_traits' con el prefijo 'std'. –

4

¡Suponiendo que su caso de uso real es un poco más complejo que un contenedor de punteros enteros!

podría retirar los contenedores PTR boost
http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/reference.html

Los contenedores contener objetos asignados dinámicamente (es decir, punteros).
Pero todo acceso a los objetos (directo o vía iterador) devuelve una referencia al objeto.

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

Bueno, esto está bien si quieres que el contenedor tenga la propiedad de los elementos. indirect_iterator parece más apropiado cuando se trata de punteros para objetar con entidad semántica que ya son propiedad de otra cosa (o asignados en la pila). –

Cuestiones relacionadas