目前,我只能做远程基于循环与此:使用时所需的迭代器范围为基础的for循环
for (auto& value : values)
但有时我需要一个迭代的价值,而不是引用(无论出于何种原因) 。是否有任何方法无需通过比较值的整个矢量?
目前,我只能做远程基于循环与此:使用时所需的迭代器范围为基础的for循环
for (auto& value : values)
但有时我需要一个迭代的价值,而不是引用(无论出于何种原因) 。是否有任何方法无需通过比较值的整个矢量?
使用旧for
环路:
for (auto it = values.begin(); it != values.end(); ++it)
{
auto & value = *it;
//...
}
有了这个,你已经value
以及迭代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
始终保持同步。
范围基于for
循环作为在Java中的C++对口foreach
允许阵列元件容易迭代创建。它是为了消除像迭代器这样的复杂结构的使用,以使其变得简单。我想要一个iterator
,正如纳瓦兹所说,你将不得不使用正常的for
循环。
我希望他们会提供一个类似的循环,而不是迭代器,尽管:( –
我很高兴,你得到的是他们的价值,而不是迭代器,因为我基于范围'for'是语法糖和减少打字量。取消引用迭代器会使其容易出错,尤其是在使用'auto' – TeaOverflow
这是一个代理包装类,允许您通过将其隐藏到自己的变量中来公开隐藏的迭代器。
#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';
}
+1进行封装实验时。:-) – Nawaz
我想我就这个问题和找到解决方案。
用法:
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);
}
请*,*使用'ForIterator'的函数模板... – Xeo
啊,嗯,是。我没有完全明白,编译器可以从构造函数中获得他的T ...所以我想到了decltype并且看到了用法膨胀......并且我没有看到它可以从函数中获得他的T ...函数模板,谢谢。是对的,我现在怎么做? – payload
是的,看起来不错。 FWIW,虽然有'boost :: counting_iterator',但确实如此,并且方便地用'boost :: counting_range'包装,所以你可以这样写:for(auto it:boost :: counting_range(r.begin(), r.end()))'。 :) – Xeo
有做这std::vector
,这也应该工作,如果你是在调整向量的一个非常简单的方法过程(我不确定接受的答案是否考虑这种情况)
如果b
是您的矢量,哟你可以做
for(auto &i:b){
auto iter = b.begin() + (&i-&*(b.begin()));
}
其中iter
将是您所需的迭代器。
如果您已经在利用C++向量连续的事实,那么您也可以利用这样一个事实:任何理智的实现都只是将'vector
让我们这样做很脏... 我知道,0x70h与堆栈的使用,编译器版本变化,.... 应该被编译器暴露出来,但它不是:-(
char* uRBP = 0; __asm { mov uRBP, rbp }
Iterator** __pBegin = (Iterator**)(uRBP+0x70);
for (auto& oEntry : *this) {
if (oEntry == *pVal) return (*__pBegin)->iPos;
}
是啊,这就是我我只是想知道是否有基于范围的循环的解决方案 –
@小太郎:查看编辑 – Nawaz
我同意旧的for循环的第一个解决方案好得多:P –