c++ - iteradores - que es un iterador en java
Descartar la salida de una función que necesita un iterador de salida (4)
¿Tienes Boost disponible? Si es así, podría usar un function_output_iterator envolviendo una función vacía.
Aunque no es ideal. Cualquiera que sea el iterador que use, necesitará crear una instancia de value_type para return in operator *, incluso si lo descarta.
Supongamos que hay una función de plantilla en C ++ que hace un trabajo útil pero también genera una secuencia de valores a través de un iterador de salida. Ahora supongamos que esa secuencia de valores a veces es interesante, pero en otros no es útil. ¿Hay una clase de iterador lista para usar en el STL que pueda ser instanciada y pasada a la función e ignorará los valores que la función intente asignar al iterador de salida? Para decirlo de otra manera, envíe todos los datos a / dev / null?
No es difícil escribir uno.
template<typename T>
class NullOutputIterator
{
public:
NullOutputIterator() {}
NullOutputIterator& operator++() { return *this; }
NullOutputIterator& operator++(int) { return *this; }
T& operator*() { return m; }
T* operator->() { return &m; }
private:
T m;
};
No lo he probado, y probablemente falte algo importante, pero creo que esta es la idea.
El STL no proporciona dicho iterador. Pero podría codificarlo usted mismo (probó ese código):
struct null_output_iterator :
std::iterator< std::output_iterator_tag,
null_output_iterator > {
/* no-op assignment */
template<typename T>
void operator=(T const&) { }
null_output_iterator & operator++() {
return *this;
}
null_output_iterator operator++(int) {
return *this;
}
null_output_iterator & operator*() { return *this; }
};
No necesita ningún dato al usarlo como resultado del operator*
. El resultado de *it = x;
no se usa en los requisitos del iterador de salida, por lo que podemos darle un tipo de void
de retorno.
Editar: veamos cómo funciona este operator*
. El estándar dice en 24.1.2 / 1 sobre los requisitos de un iterador de salida que en ambos casos:
*it = t;
*it++ = t;
Que el resultado de esas expresiones no se usa. Eso es lo que hace que esto funcione:
null_output_iterator it;
*it; // returns a null_output_iterator& per definition of the `operator*`.
*it = some_value; // returns void per definition of the templated `operator=`.
Ahora no necesitamos tener ningún dato que devolvamos en el operator*
: simplemente usamos el iterador mismo. Tenga en cuenta que el operador con plantilla = no sobrescribe el operador de asignación de copia integrado. Todavía se proporciona.
Basé el mío en std :: back_insert_iterator , pero sin el contenedor:
#include <iterator>
template<typename T>
class NullOutputIter
: public std::iterator<std::output_iterator_tag,void,void,void,void>
{
public:
NullOutputIter &operator=(const T &) { return *this; }
NullOutputIter &operator*() { return *this; }
NullOutputIter &operator++() { return *this; }
NullOutputIter operator++(int) { return *this; }
};
Esto es similar a la respuesta de Johannes, pero sin la plantilla operator=
que toma lo que sea. Me gusta escribir fuerte Quiero que *it = wrong_type_thing
sea un error en tiempo de compilación. También esto usa void
para los diversos parámetros de la plantilla para std::iterator
, como los iteradores de salida en la biblioteca estándar.
Esto también es similar a la solución de Mark, pero (a) hereda correctamente de std::iterator
y (b) no tiene la variable de estado interno innecesaria.