2008-12-17 13 views
6

¿Hay alguna manera de que pueda encontrar el contenedor al que apunta un iterador? Específicamente, quiero ser capaz de encontrar el std :: vector apuntado por un std :: vector :: iterator en particular para que pueda verificar el rango, sin tener que pasar referencias a ese vector.Encontrar el propietario de un iterador STL

Si (como sospecho) la respuesta es no, ¿por qué no?

corregir: gracias por una serie de respuestas rápidas y (en gran medida) exactas. Evan Teran lo clava. No estaba pensando en la optimización en absoluto, pero ahora es obvio.

Un par de personas me preguntaron para qué quiero hacer esto. No es nada terriblemente importante. Tengo un objeto que se inicializa con un vector y un iterador apuntando al vector. Sería lindo y conveniente si pudiera inicializar el objeto solo con un iterador, porque entonces podría convertir vectores :: iteradores directamente a este objeto (esto suena extraño pero tiene sentido en el caso particular). Pero no es crucial en absoluto.

Respuesta

6

No lo creo. Si los iteradores tenían que mantener una referencia/puntero al propietario, entonces sería imposible que se optimizaran hasta un puntero liviano (lo que se puede hacer con contenedores que garanticen el almacenamiento contiguo como vectores, etc.).

0

No creo que haya un método expuesto para hacer eso. La razón es que ese no es el propósito del iterador. Por supuesto, no existe una razón técnica por la que un iterador no pueda contener un puntero a su contenedor padre. Incluso si se implementa de tal manera que no requiere ese puntero, aún podría contenerlo.

Los iteradores están destinados a iterar sobre la colección, y como tales, proporcionan la interfaz necesaria para hacer eso y solo eso. Esto es buenos principios de programación orientada a objetos.

¿Puedo preguntar cuál es su caso de uso, que necesita saber el "rango" del contenedor con un iterador?

3

No se puede recuperar el contenedor de un iterador de forma general. Como un ejemplo de por qué, un puntero sin formato puede ser utilizado como un iterador:

#include <algorithm> 
#include <cstdio> 
#include <cstring> 

int 
main(int argc, char *argv[]) 
{ 
     const char s[] = "Hello, world!"; 
     const char *begin = s; 
     const char *end = s + strlen(s); 

     std::for_each(begin, end, putchar); 

     return 0; 
} 

¿Cómo podría recuperar la cadena original a partir de un puntero (si no está orientado hacia el principio de la cadena)?

Sin embargo, si necesita esta funcionalidad, entonces siempre puede implement su propio contenedor alrededor del iterador que almacena una referencia al contenedor.

+0

No creo que esto realmente tenga algo que ver con la pregunta que se hizo ... – jdmichal

+3

Demuestra por qué no se puede obtener el contenedor de una iteración con un ejemplo concreto y simple ... –

2

En teoría, hay una manera si el iterador en cuestión es al menos un iterador directo. Puede verificar si su iterador es uno de los iteradores en [primero, último] para cada contenedor candidato. Como está utilizando un contenedor vectorial, tiene un iterador de acceso aleatorio, puede usar el operador inferior para hacer esta comprobación rápidamente.

TIENE que conocer todos los vectores candidatos contra los cuales verificar por adelantado, y esta no es una forma general de obtener el contenedor al que pertenece un iterador.

Puede, sin embargo, definir una extensión de iteradores de acceso aleatorio decorando el iterador de acceso aleatorio con algo que contenga un puntero al vector de creación. Es probable que sea levemente poco elegante, ineficiente e inconveniente. Así que vea si puede reescribir el código para evitar esta necesidad primero.

+1

Esta primera sugerencia definitivamente se basa en detalles de implementación no declarados, y será muy difícil de mantener. Prefiero implementar el decorador; al menos entonces está garantizado que siempre funciona y hace que mis intenciones sean obvias. – jdmichal

+0

Incorrecto. La primera sugerencia se basa en los iteradores de verificación de igualdad de capacidades, que es oficialmente compatible, o en la capacidad de

+0

Me gustaría retractar mi comentario anterior, pero lo dejo para la posteridad. De hecho, la solución requeriría apoyarse en iteradores de acceso aleatorio que básicamente se implementan como punteros o algo así como punteros que implican ubicaciones en un espacio de direcciones (bajo la definición técnica de "espacio de direcciones"). No veo una definición limpia y estandarizada de lo que sucede si se comparan los iteradores de acceso aleatorio que surgen de diferentes contenedores. –

1

El STL no permite esto.

Los iteradores de Vecor, por ejemplo, pueden implementarse simplemente como un puntero. Y no hay una forma general de recuperar un objeto de un puntero que apunta a algunos datos que el objeto ha asignado.

0

Como se sugirió anteriormente, es mejor reescribir el código para que no necesite este comportamiento. Es lo mismo que sostener una moneda, pero no tienes idea de dónde viene, a menos que lo hayas anotado en un papel.

Si no puede volver a escribir el código, puede introducir un objeto de envoltura que contenga un puntero al contenedor y al propio iterador. ¿Para qué necesitas esto específicamente?

4

No hay forma de hacerlo funcionar. La razón es simple: al agregar un camino a los iteradores para obtener el contenedor al que apuntan, está

  • Sin sentido. Iteradores iteran sobre una colección. Como otros dijeron, solo eso, nada más.
  • No es compatible con los requisitos del iterador. Recuerde que un puntero es un iterador de acceso aleatorio. Colocar un puntero de contenedor en el iterador no sería útil para los algoritmos, ya que pretenden ser genéricos, desacoplados de implementaciones de iterador específicas. Un puntero utilizado como un iterador no puede tener un puntero a la matriz de la que se tomó como miembro.

Dice que lo necesita para verificar el rango. Puede proporcionar un iterador final que apunta uno después de la última posición válida del iterador de un rango. Verifica si tu posición actual no está al final. Eso es todo lo que necesita hacer para verificar el rango.

Cuestiones relacionadas