¿Cuáles son los casos de uso típicos de un iterator_trait?

3 minutos de lectura

avatar de usuario
San

Soy nuevo en C ++, así que tengan paciencia conmigo. Estoy tratando de entender STL iterator_traits. En el libro “The C++ Standard Library” la estructura iterator_traits se define de la siguiente manera:

template <class T>
struct iterator_traits {
  typedef typename T::value_type value_type;
  typedef typename T::difference_type difference_type;
  typedef typename T::iterator_category iterator_category;
  typedef typename T::pointer pointer;
  typedef typename T::reference reference;
};

Entonces me parece que está reexponiendo los subtipos que T ya expone. Avanzando más, el libro da un ejemplo de cómo usarlo, que es algo como lo siguiente

template <class MyIterator>
void do_something(MyIterator start, MyIterator end) {
    typedef typename iterator_traits<MyIterator>::value_type value_type; 
    value_type v = *start;
    .....
}

Mi pregunta es ¿por qué necesito esto? iterator_traits estructura aquí, si la idea era obtener la value_typeno podría haberlo obtenido de MyIterator directamente? Mi confusión parece surgir de mi comprensión (seguramente incorrecta) de que la información de los subtipos debe obtenerse del template <class T> utilizado para instanciar el iterator_trait. Entonces, si pudiera explicar, y preferiblemente con un ejemplo, por qué y dónde necesitaría iterator_traits, eso sería muy útil.

  • Cuánto nuevo eres ? Los novatos generalmente no juegan con templates.

    – iammilind

    19 de julio de 2011 a las 3:38

  • @iammilind Bueno, había hecho algo de C y Python antes, por lo que las cosas de la clase eran algo familiares. Las plantillas no son así, así que aquí es donde estoy aprendiendo cosas nuevas.

    – san

    19 de julio de 2011 a las 3:57

  • Bueno, si usa C++ a tiempo completo durante 10 años, seguirá aprendiendo cosas nuevas sobre plantillas en 2021 🙂

    –James McNellis

    19 de julio de 2011 a las 4:15

  • ¡Hola! soy de 2021; He estado usando C++ a tiempo completo durante 10 años; y puedo confirmar que sigo aprendiendo cosas nuevas sobre plantillas.

    – Chip Hog

    8 sep 2021 a las 18:00

Los punteros a una matriz se pueden usar como iteradores de acceso aleatorio.

Tiene que haber alguna forma coherente de obtener estos tipos tanto para los punteros (que obviamente no pueden tener los tipos declarados como tipos anidados, ya que solo las clases pueden tener tipos anidados) y para los iteradores de tipo de clase. La plantilla de clase de rasgos proporciona esta forma consistente.

los iterator_traits la plantilla de clase está especializada para punteros como este:

template <typename T>
struct iterator_traits<T*>
{
    typedef std::random_access_iterator_tag iterator_category;
    typedef T                               value_type;
    typedef T*                              pointer;
    typedef T&                              reference;
    typedef std::ptrdiff_t                  difference_type;
};

  • ¡Ay! entonces el punto es hacer do_something trabajar con punteros así como con iteradores basados ​​en clases. Gracias.

    – san

    19 de julio de 2011 a las 4:02

  • Sí. Los rasgos también son útiles por otras razones (son bastante útiles cuando se usa el patrón de plantilla curiosamente recurrente, por ejemplo), pero esta es la razón específica por la que tenemos iterator_traits.

    –James McNellis

    19 de julio de 2011 a las 4:14

  • Además, si usa una clase similar a un iterador de terceros que no sigue el protocolo, puede adaptarla especializándose std::iterator_traits<IteratorLikeClass>.

    – alfC

    4 de diciembre de 2018 a las 15:29

¿Ha sido útil esta solución?