C++ 基于范围的循环和多迭代器
我有以下代码,表示3D应用程序中的网格(为了清晰起见,有些代码是经过修改的): 对我来说有点冗长。我首选的客户端代码将改为如下所示:C++ 基于范围的循环和多迭代器,c++,c++11,for-loop,iterator,ranged-loops,C++,C++11,For Loop,Iterator,Ranged Loops,我有以下代码,表示3D应用程序中的网格(为了清晰起见,有些代码是经过修改的): 对我来说有点冗长。我首选的客户端代码将改为如下所示: for(auto & vert : mesh.vertices) { // Do stuff. } for(auto & element : mesh.elements) { // Do stuff. } 是否可以在不公开容器的实现细节的情况下实现这一点?另外,我不想将容器包装到自定义类中,因为我希望完全访问Mesh类中所选的容器(std::v
for(auto & vert : mesh.vertices) {
// Do stuff.
}
for(auto & element : mesh.elements) {
// Do stuff.
}
是否可以在不公开容器的实现细节的情况下实现这一点?另外,我不想将容器包装到自定义类中,因为我希望完全访问Mesh类中所选的容器(std::vector)。分别将函数
verticesBegin
和verticesEnd
重命名为begin
和end
。那么你就可以写下:
for(auto & vert : mesh)
{
// Do stuff.
}
请注意,基于范围的for
循环希望容器具有开始
和结束
作为成员函数,或者自由函数开始
和结束
,将容器作为参数
还要注意,基于范围的for循环不能迭代两件事-mesh
可以像一个容器一样工作,而不是两个。所以,如果你想迭代索引,那么你必须公开它,或者抽象它,然后公开顶点
或者您可以编写一个zip迭代器,它将在一个for循环中同时在两个容器上进行迭代。使用代理存储两个迭代器并实现begin和end方法非常简单:
#include <iostream>
#include <vector>
template <typename T>
struct PairIt {
PairIt(T&& b, T&& e) : b_{std::forward<T>(b)}, e_{std::forward<T>(e)} {}
T begin() const { return b_; }
T end() const { return e_; }
private:
T b_,e_;
};
std::vector<int> badglobal { 1, 2, 3 };
PairIt<std::vector<int>::iterator> ForRangeProxy() {
return { begin(badglobal), end(badglobal) };
};
int main() {
for( auto v : ForRangeProxy() )
std::cout << v << std::endl;
}
#包括
#包括
模板
结构对{
PairIt(T&&b,T&&e):b{std::forward(b)},e{std::forward(e)}
T begin()常量{return b_;}
T end()常量{return e_;}
私人:
T b_,e_;
};
std::向量{1,2,3};
PairIt ForRangeProxy(){
返回{begin(BADGALOBAL),end(BADGALOBAL)};
};
int main(){
for(自动v:ForRangeProxy())
std::cout您可以从顶点()
和元素()
函数返回迭代器包装器,这些函数可以传递给for循环,例如
template<typename T>
class iterator_wrapper
{
public:
iterator_wrapper(const typename std::vector<T>::const_iterator &begin_,
const typename std::vector<T>::const_iterator &end_)
:m_begin(begin_), m_end(end_) {}
typename std::vector<T>::const_iterator begin() const {return m_begin;}
typename std::vector<T>::const_iterator end() const {return m_end;}
private:
typename std::vector<T>::const_iterator m_begin, m_end;
};
那么就这样称呼它:
for(auto &vert:mesh.vertices())
{
//....
}
for(auto &element:mesh.elements())
{
//....
}
您可以使用某种代理,例如:
template<typename Container>
class ConstIteratorProxy
{
public:
ConstIteratorProxy(const Container& container) : container_(container) { }
typename Container::const_iterator begin() const {
return container_.begin();
};
typename Container::const_iterator end() const {
return container_.end();
};
private:
const Container& container_;
};
+1但是,如果他也想迭代网格索引呢?这需要更多的努力,正如@Manu343726所说,我想以同样的方式迭代索引。我将在问题中澄清这一点。@MorganBengtsson:基于范围的for循环不能迭代两件事。mesh
可以像一个容器,而不是两个.So如果你也想迭代索引,那么你必须公开它。或者写一个zip迭代器。我不知道为什么标准库中没有zip迭代器
iterator_wrapper<Vertex> vertices() {return iterator_wrapper<Vertex>(vertices_.begin(), vertices_.end());}
iterator_wrapper<int> elements() {return iterator_wrapper<int>(elements_.begin(), elements_.end());}
for(auto &vert:mesh.vertices())
{
//....
}
for(auto &element:mesh.elements())
{
//....
}
template<typename Container>
class ConstIteratorProxy
{
public:
ConstIteratorProxy(const Container& container) : container_(container) { }
typename Container::const_iterator begin() const {
return container_.begin();
};
typename Container::const_iterator end() const {
return container_.end();
};
private:
const Container& container_;
};
ConstIteratorProxy<Vertices> vertices() const {
return ConstIteratorProxy<Vertices>(vertices_);
}
ConstIteratorProxy<Elements> elements() const {
return ConstIteratorProxy<Elements>(elements_);
}
Mesh m;
for (auto& v : m.vertices()) { }
for (auto& e : m.elements()) { }