有没有一种方法可以使用for-range循环语法来处理数组中的两个顺序元素?
例如..。
func( std::vector< vec2 > &points )
{
std::vector< float > distances;
for( int i = 0; i < (int)points.size() - 1; i++ )
{
auto from = points.at( i );
auto to = points.at( i + 1 );
distances.push_back( magnitude( to - from ) );
}
}发布于 2017-11-13 21:18:42
有没有一种方法可以使用for-range循环语法来处理数组中的两个顺序元素?
不是从盒子里出来的。
但是,您可以滚动自己的包装类和迭代器类来获得所需的内容。
包装类的begin()和end()成员函数必须返回一个迭代器,该迭代器在用*操作符取消引用时计算为std::pair。
下面是一个演示程序:
#include <iostream>
#include <vector>
struct VectorWrapper;
struct MyIterator
{
MyIterator(VectorWrapper const& wrapper, size_t index) : wrapper_(wrapper), index_(index) {}
std::pair<float, float> operator*();
MyIterator& operator++()
{
++index_;
return *this;
}
bool operator==(MyIterator const& rhs) const
{
return (this->index_ == rhs.index_);
}
bool operator!=(MyIterator const& rhs) const
{
return (this->index_ != rhs.index_);
}
VectorWrapper const& wrapper_;
size_t index_;
};
struct VectorWrapper
{
explicit VectorWrapper(std::vector<float>& distances) : distances_(distances) {}
MyIterator begin() const
{
return MyIterator(*this, 0);
}
MyIterator end() const
{
return MyIterator(*this, distances_.size()-1);
}
std::vector<float>& distances_;
};
std::pair<float, float> MyIterator::operator*()
{
return std::make_pair(wrapper_.distances_[index_], wrapper_.distances_[index_+1]);
}
int main()
{
std::vector<float> dist = {1, 2, 3, 4, 5, 6};
VectorWrapper wrapper(dist);
for ( auto item : wrapper )
{
std::cout << item.first << ", " << item.second << std::endl;
}
}及其产出:
1, 2
2, 3
3, 4
4, 5
5, 6发布于 2017-11-13 21:35:04
在有一些库帮助的c++17中,您可以让它工作:
for (auto&&[ from, to ] : adjacent_overlapped_zip( points ) ) {
distances.push_back( magnitude( to-from) );
}其中,adjacent_overlapped_zip在对或点元组上返回一系列附加迭代器。
template<class It>
struct range {
It b; It e;
It begin() const{ return b; }
It end() const{ return e; }
bool empty() const{ return begin()==end(); }
range without_front( std::size_t n = 1 ) const {
return {std::next(begin(), n), end()};
}
range without_back( std::size_t n = 1 ) const {
return {begin(), std::prev(end(), n)};
}
};
template<class It>
range(It b, It e)->range<It>;
template<class It>
struct adjacent_iterator:It {
auto operator*()const {
return std::make_pair( It::operator*(), std::next(*this).It::operator*() );
}
using It::It;
explicit adjacent_iterator(It it):It(it) {}
};
template<class It>
explicit adjacent_iterator( It ) -> adjacent_iterator<It>;
// TODO: support pointers
template<class C>
auto adjacent_overlapped_zip( C& c ) {
using std::begin; using std::end;
range r( begin(c), end(c) );
if (!r.empty()) {
r = r.without_back();
range retval( adjacent_iterator(r.begin()), adjacent_iterator(r.end()) );
return retval;
} else {
return {};
}
}或者类似的东西。以上代码可能包含键入和其他错误。
我也会受到以下诱惑:
for (auto&&[ from, to ] : transform( [](auto it){ return std::make_pair( *it, *std::next(it)); }, range( iterators_of( points ) ).without_back() ) )
distances.push_back( magnitude( to-from) );
}有一组稍微花哨的原语。范围-v3将使这更好。
在原始的c++11中,不,你运气不好。
https://stackoverflow.com/questions/47273606
复制相似问题