В настоящее время я могу делать только циклы на основе дальности с этим:
for (auto& value : values)
Но иногда мне нужен итератор для значения вместо ссылки (по какой-то причине). Есть ли какой-либо метод без необходимости проходить через весь вектор, сравнивая значения?
std::find
если вам нужно найти значение ... Старые добрые алгоритмы все еще находятся в новом стандарте.value
иit
может не синхронизироваться. Помнитеvalue
, это ссылка.++it
чтобы поit++
мере возможности (оба использования в вашем коде) , как это могло бы иметь меньшую нагрузку.Вот класс-оболочка прокси, который позволяет вам раскрыть скрытый итератор, присвоив ему псевдоним вашей собственной переменной.
#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 ); }
Применение:
#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'; }
источник
Я попробовал себя и нашел решение.
Применение:
for(auto i : ForIterator(some_list)) { // i is the iterator, which was returned by some_list.begin() // might be useful for whatever reason }
Реализация была не такой уж и сложной:
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); }
источник
boost::counting_iterator
правда, которая делает именно то, что и удобно обматываютboost::counting_range
, так что вы можете написать:for(auto it : boost::counting_range(r.begin(), r.end()))
. :)operator++()
должен вернутьInnerIterator
, в противном случае очень мило и уродливо.for
Цикл на основе диапазона создается как аналог C ++ дляforeach
в java, который позволяет легко итерировать элементы массива. Он предназначен для устранения использования сложных структур, таких как итераторы, чтобы упростить его. Я хочу, чтобыiterator
, как сказал Наваз, вам придется использовать обычныйfor
цикл.источник
for
на синтаксическом сахаре и о сокращении количества наборов. Необходимость разыменовать итератор сделает его подверженным ошибкам, особенно при использовании сauto
Существует очень простой способ сделать это для
std::vector
, который также должен работать, если вы изменяете размер вектора во время процесса (я не уверен, учитывает ли принятый ответ этот случай)Если
b
это ваш вектор, вы можете просто сделатьfor(auto &i:b){ auto iter = b.begin() + (&i-&*(b.begin())); }
где
iter
будет ваш требуемый итератор.Это использует тот факт, что векторы C ++ всегда смежны .
источник
vector<T>::iterator
дляT*
: Проверьте это с помощьюstatic_assert()
, а затем просто используйтеT* iter = &i;
.Давайте сделаем это очень грязно ... Я знаю, что 0x70h меняется в зависимости от использования стека, версии компилятора ... Он должен отображаться компилятором, но это не так :-(
char* uRBP = 0; __asm { mov uRBP, rbp } Iterator** __pBegin = (Iterator**)(uRBP+0x70); for (auto& oEntry : *this) { if (oEntry == *pVal) return (*__pBegin)->iPos; }
источник