Para iteradores como los devueltos por std::back_inserter()
, ¿hay algo que se pueda utilizar como un iterador "final"?iterador "end()" para insertadores posteriores?
esto parece un poco sin sentido al principio, pero tengo una API que es:
template<typename InputIterator, typename OutputIterator>
void foo(
InputIterator input_begin,
InputIterator input_end,
OutputIterator output_begin,
OutputIterator output_end
);
foo
realiza alguna operación en la secuencia de entrada, generando una secuencia de salida. (Longitud del que se sabe que foo
pero puede o no ser igual a la longitud de la secuencia de entrada.)
La toma del parámetro output_end
es la parte extraña: std::copy
no lo hace, por ejemplo, y que asume' No voy a pasarlo basura. foo
lo hace para proporcionar verificación de rango: si pasas un rango demasiado pequeño, arroja una excepción, en el nombre de la programación defensiva. (En lugar de sobreescribir potencialmente bits aleatorios en la memoria.)
Ahora, supongamos que quiero pasar foo
un insertador posterior, específicamente uno de un std::vector
que no tiene límite fuera de las limitaciones de memoria. Todavía necesito un iterador "final", en este caso, algo que nunca se comparará igual. (O, si tuviera un std::vector
pero con una restricción en la longitud, ¿quizás a veces podría ser igual?)
¿Cómo hago esto? Tengo la capacidad de cambiar la API de foo
. ¿Es mejor no verificar el rango y, en su lugar, proporcionar un medio alternativo para obtener el rango de salida requerido? (Que se necesitaría de todos modos para matrices en bruto, pero no se requiere para insertadores posteriores en un vector). Esto parecería menos robusto, pero estoy luchando para que el trabajo "robusto" (arriba) funcione.
Este es un enfoque razonable. No había pensado en verificar si 'out_it == out_end' en cada iteración en vez de calcular la distancia. Si el algoritmo pudiera modificarse de forma tal que los dos iteradores de salida pudieran ser de tipos diferentes (usando dos parámetros de plantilla), esto podría simplificarse simplemente con un iterador 'back_inserter_end' que, cuando se compara con cualquier iterador, no es igual. Eso haría mucho menos código, pero posiblemente sea más complicado. Todavía no creo que el control de rango como este sea una gran idea, pero si realmente se desea, ¡esta es una buena forma de lograrlo! –
@James: Ese iterador 'back_inserter_end' parece tentador ... Sería bueno si todos los iteradores tuvieran un valor" NULO "como lo hacen los punteros, ya que ese valor podría usarse en lugar de necesitar un tipo diferente para mantenerlo. Oh bien. –
Estas son respuestas excelentes, y me gustaría poder marcar "Respuesta aceptada" en más de una cosa. He subido la apuesta a la tuya (aunque desearía poder +2), pero le doy a James la Respuesta Aceptada ya que esa es la solución con la que voy. (Esto va a ser una biblioteca, por lo que no estoy seguro de exponer esto en una API externa) Esto fue definitivamente informativo e interesante, gracias por tomarse el tiempo para publicarlo. – Thanatos