현재 다음과 같이 범위 기반 루프 만 수행 할 수 있습니다.
for (auto& value : values)
그러나 때로는 참조 대신 값에 대한 반복자가 필요합니다 (어떤 이유로 든). 값을 비교하는 전체 벡터를 거치지 않고 방법이 있습니까?
답변:
이전 for
루프를 다음과 같이 사용하십시오 .
for (auto it = values.begin(); it != values.end(); ++it )
{
auto & value = *it;
//...
}
이것으로 당신은 value
iterator뿐만 아니라 it
. 사용하고 싶은 것을 사용하십시오.
편집하다:
권장하지는 않지만 범위 기반 for
루프 를 사용하려면 (예, 어떤 이유로 든 : D) 다음을 수행 할 수 있습니다.
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
}
이 접근 방식은 및 항상 동기화 value
되기 때문에 주어진 검색을 피 합니다.value
it
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
.
이 작업을 수행하는 매우 간단한 방법이 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;
}