c++ - sirve - recorrer list integer java
Necesita iterador cuando usa bucles basados en rangos (6)
Aquí hay una clase de derivador proxy que le permite exponer el iterador oculto allisándolo a su propia variable.
#include <memory>
#include <iterator>
/* Only provides the bare minimum to support range-based for loops.
Since the internal iterator of a range-based for is inaccessible,
there is no point in more functionality here. */
template< typename iter >
struct range_iterator_reference_wrapper
: std::reference_wrapper< iter > {
iter &operator++() { return ++ this->get(); }
decltype( * std::declval< iter >() ) operator*() { return * this->get(); }
range_iterator_reference_wrapper( iter &in )
: std::reference_wrapper< iter >( in ) {}
friend bool operator!= ( range_iterator_reference_wrapper const &l,
range_iterator_reference_wrapper const &r )
{ return l.get() != r.get(); }
};
namespace unpolluted {
/* Cannot call unqualified free functions begin() and end() from
within a class with members begin() and end() without this hack. */
template< typename u >
auto b( u &c ) -> decltype( begin( c ) ) { return begin( c ); }
template< typename u >
auto e( u &c ) -> decltype( end( c ) ) { return end( c ); }
}
template< typename iter >
struct range_proxy {
range_proxy( iter &in_first, iter in_last )
: first( in_first ), last( in_last ) {}
template< typename T >
range_proxy( iter &out_first, T &in_container )
: first( out_first ),
last( unpolluted::e( in_container ) ) {
out_first = unpolluted::b( in_container );
}
range_iterator_reference_wrapper< iter > begin() const
{ return first; }
range_iterator_reference_wrapper< iter > end()
{ return last; }
iter &first;
iter last;
};
template< typename iter >
range_proxy< iter > visible_range( iter &in_first, iter in_last )
{ return range_proxy< iter >( in_first, in_last ); }
template< typename iter, typename container >
range_proxy< iter > visible_range( iter &first, container &in_container )
{ return range_proxy< iter >( first, in_container ); }
Uso:
#include <vector>
#include <iostream>
std::vector< int > values{ 1, 3, 9 };
int main() {
// Either provide one iterator to see it through the whole container...
std::vector< int >::iterator i;
for ( auto &value : visible_range( i, values ) )
std::cout << "# " << i - values.begin() << " = " << ++ value << ''/n'';
// ... or two iterators to see the first incremented up to the second.
auto j = values.begin(), end = values.end();
for ( auto &value : visible_range( j, end ) )
std::cout << "# " << j - values.begin() << " = " << ++ value << ''/n'';
}
Actualmente, solo puedo hacer loops basados en rangos con esto:
for (auto& value : values)
Pero a veces necesito un iterador para el valor, en lugar de una referencia (por el motivo que sea). ¿Hay algún método sin tener que pasar por todo el vector comparando valores?
Hay una forma muy simple de hacer esto para std::vector
, que también debería funcionar si está cambiando el tamaño del vector durante el proceso (no estoy seguro de si la respuesta aceptada considera este caso)
Si b
es su vector, puede hacer
for(auto &i:b){
auto iter = b.begin() + (&i-&*(b.begin()));
}
donde iter
será su iterador requerido.
Esto aprovecha el hecho de que los vectores C ++ son siempre contiguos .
Me probé con esto y encontré una solución.
Uso:
for(auto i : ForIterator(some_list)) {
// i is the iterator, which was returned by some_list.begin()
// might be useful for whatever reason
}
La implementación no fue tan difícil:
template <typename T> struct Iterator {
T& list;
typedef decltype(list.begin()) I;
struct InnerIterator {
I i;
InnerIterator(I i) : i(i) {}
I operator * () { return i; }
I operator ++ () { return ++i; }
bool operator != (const InnerIterator& o) { return i != o.i; }
};
Iterator(T& list) : list(list) {}
InnerIterator begin() { return InnerIterator(list.begin()); }
InnerIterator end() { return InnerIterator(list.end()); }
};
template <typename T> Iterator<T> ForIterator(T& list) {
return Iterator<T>(list);
}
Use el viejo bucle for
como:
for (auto it = values.begin(); it != values.end(); ++it )
{
auto & value = *it;
//...
}
Con esto, tiene value
y lo itera. Usa lo que quieras usar.
EDITAR:
Aunque no lo recomendaría, pero si desea usar el bucle for
basado for
rangos (sí, por cualquier razón : D), puede hacer esto:
auto it = std::begin(values); //std::begin is a free function in C++11
for (auto& value : values)
{
//Use value or it - whatever you need!
//...
++it; //at the end OR make sure you do this in each iteration
}
Este enfoque evita buscar value
dado, ya que el value
y siempre están sincronizados.
Vamos a hacerlo muy sucio ... Lo sé, el 0x70h está cambiando con el uso de la pila, la versión del compilador, .... Debe ser expuesto por el compilador, pero no es :-(
char* uRBP = 0; __asm { mov uRBP, rbp }
Iterator** __pBegin = (Iterator**)(uRBP+0x70);
for (auto& oEntry : *this) {
if (oEntry == *pVal) return (*__pBegin)->iPos;
}
el rango basado for
loop se crea como la contraparte de c ++ para foreach
en java que permite una fácil iteración de los elementos de la matriz. Está destinado a eliminar el uso de estructuras complejas como iteradores para simplificarlo. Si desea un iterator
, como dijo Nawaz, tendrá que usar el ciclo normal for
ciclo.