できるだけ頻繁にranged for forループを使用してください。 for(;;)
ループは複雑でエラーが発生する傾向があります。
for(:)
ループを使用すると、コードを書き留めた時点から複雑さが増しますが、そのインフラストラクチャを一度書き直して再利用することができるため、コード全体にわたってバグがなくなります。ここで、で開始する
は簡単range_t
です:
template<class It>
struct range_t {
It b, e;
It begin() const { return b; }
It end() const { return e; }
std::size_t size() const { return std::distance(begin(), end()); }
using iterator_tag = typename std::iterator_traits<It>::iterator_category;
private:
static It safe_advance(It in, It bound, std::ptrdiff_t n, std::random_access_iterator_tag) const {
if (n == 0) return in;
if (n < 0) n = (std::min)(n, -std::distance(bound, in));
if (n > 0) n = (std::max)(n, std::distance(in, bound));
return std::advance(in, n);
}
static It safe_advance(It in, It bound, std::ptrdiff_t n, ...) const {
if (n == 0) return in;
while (n < 0 && in != bound) {
in = std::prev(in); --n;
}
while (n > 0 && in != bound) {
in = std::next(in); ++n;
}
return in;
}
public:
range_t without_back(std::size_t n = 1) const {
return {begin(), safe_advance(end(), begin(), -(std::ptrdiff_t)n, iterator_tag{} };
}
range_t without_front(std::size_t n = 1) const {
return {begin(), safe_advance(end(), begin(), n, iterator_tag{} };
}
bool empty() const { return begin() == end(); }
decltype(auto) front() const { return *begin(); }
decltype(auto) back() const { return *std::prev(end()); }
};
template<class It>
range_t<It> range(It b, It e) { return {b,e}; }
// rvalues blocked:
template<class C, class It = decltype(std::begin(std::declval<C&>()))>
range_t<It> range(C& c) { return range(std::begin(c), std::end(c)); }
それはイテレータの範囲を格納し、反復可能そのものです。そして
:
auto r = range(*controlPoints).without_back();
は、最後の要素なしcontrolPoints
ある範囲のオブジェクトです。遠隔ベースを使用して
あなたがこれを行うことができますのために:上記のコードは慎重に空の配列を供給して処理する
for (auto& x : range(*controlPoints).without_back()) {
}
注意を。
イテレータのイテレータを使用できるようにする同様のアダプタを作成することもできます。私は通常Index
を保存して++
と==
などを渡してindex_iterator
を書くことでこれを行います。 *
を除いて、Index
のコピーが返されます。
これは、整数に反復子を作成するのに便利ですが、反復子に反復子を作成することもできます。
は、その後、あなたのコンテナ内のイテレータのインデックスの範囲を作成し、あなたは次のようになり、構文取得する:あなたがそれらを必要とする場合も、あなたのイテレータを与えるあなたは
for (auto it : iterators_into(*controlPoints)) {
}
与える範囲ベースのループを。
明示的に明記するだけで、 'it!= stop'条件がそのケースでは動作しないので、' list <> 'があらかじめ空でないことを確認してください(未定義の動作です)。 –