Actualmente, solo puedo hacer bucles a distancia con esto:
for (auto& value : values)
Pero a veces necesito un iterador para el valor, en lugar de una referencia (por cualquier motivo). ¿Existe algún método sin tener que pasar por todo el vector comparando valores?
std::find
si lo que necesita es localizar un valor ... Los buenos algoritmos antiguos todavía están en el nuevo estándar.value
yit
puede que no esté sincronizado. Recuerdevalue
es una referencia.++it
queit++
sea posible (ambos usos en su código), ya que podría tener una sobrecarga menor.Aquí hay una clase contenedora de proxy que le permite exponer el iterador oculto asigná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'; }
fuente
Me probé en 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); }
fuente
boost::counting_iterator
sin embargo, que hace exactamente eso, además de estar envuelto conboost::counting_range
, por lo que puede escribir:for(auto it : boost::counting_range(r.begin(), r.end()))
. :)operator++()
debería devolver unInnerIterator
, por lo demás muy agradable y uesful.El
for
bucle basado en rango se crea como la contraparte de c ++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 hacerlo simple. Si quieres uniterator
, como dijo Nawaz, tendrás que usar unfor
bucle normal .fuente
for
azúcar de sintaxis y en la reducción de la cantidad de escritura. Tener que desreferenciar el iterador lo haría propenso a errores, especialmente cuando se usa conauto
Hay una forma muy simple de hacer esto
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 tu vector, puedes hacerfor(auto &i:b){ auto iter = b.begin() + (&i-&*(b.begin())); }
donde
iter
estará su iterador requerido.Esto aprovecha el hecho de que los vectores de C ++ son siempre contiguos .
fuente
vector<T>::iterator
paraT*
: Verifique eso con astatic_assert()
, luego simplemente useT* iter = &i;
.Hagámoslo muy sucio ... Lo sé, el 0x70h está cambiando con el uso de la pila, la versión del compilador, ... El compilador debería exponerlo, pero no lo es :-(
char* uRBP = 0; __asm { mov uRBP, rbp } Iterator** __pBegin = (Iterator**)(uRBP+0x70); for (auto& oEntry : *this) { if (oEntry == *pVal) return (*__pBegin)->iPos; }
fuente