必要なのはrange_difference
関数です。私は Boost.Range がこのようなものを提供すると思っていましたが、彼らのドキュメントには何も見つかりませんでした (まあ、私はあまり徹底的に検索しませんでした...)。
次の関数は、(first1,last1) で示される範囲と (first2,last2) で示される範囲の差の結果を含む範囲のペアを返します。前提条件として、first1 は first2 の前または同じ位置に配置する必要があります。
template <typename InputIterator>
std::pair<
std::pair<InputIterator, InputIterator>,
std::pair<InputIterator, InputIterator> >
range_difference(InputIterator first1, InputIterator last1,
InputIterator first2, InputIterator last2)
{
typedef std::pair<InputIterator, InputIterator> Range;
InputIterator it;
// first1 must be <= first2
for (it = first1 ; it != last1 && it != first2 ; ++it);
Range left_range = std::make_pair(first1, it); // Left range
if (it == last1)
return std::make_pair(left_range, std::make_pair(first2, first2));
// it == first2
while (it != last1 && it != last2) ++it;
return std::make_pair(left_range, std::make_pair(it, last1)); // Right range
}
range2 が range1 に完全に含まれている場合、差の結果は 2 つの部分で構成されます。左の範囲と右の範囲になります。
|_____________________|__________________|________________________|
first1 first2 last2 last1
この場合、関数は (first1, first2),(last2, last1) を返します。
この別の構成では、
|_____________________| |________________________|
first1 last1 first2 last2
関数は (first1, last1),(first2, first2) を返します。他にも多くの可能な構成があります。ただし、知っておくべき重要なことの 1 つは、右側の範囲が空の場合、max(first2, last1)に配置されるということです。この例で、これがどのように必要であるかがわかります。
最後に、first1 と first2 が同じ位置にある場合、返される左側の範囲は空の id (first1,first1) になります。
では、この関数を使用して問題を解決するにはどうすればよいでしょうか。「非アクティブ化」範囲ではかなり簡単ですが、「アクティブ化」範囲では少しトリッキーです。
typedef std::vector<Activable>::iterator Iterator;
Iterator old_beg, old_end, new_beg, new_end; // Old and new ranges
typedef std::pair<Iterator, Iterator> Range;
typedef std::pair<Range, Range> SplitRange;
SplitRange deactivate = range_difference(old_beg, old_end, new_beg, new_end);
// Left range
for (Iterator it = deactivate.first.first;
it != deactivate.first.second;
++it)
it->deactivate();
// Right range
for (Iterator it = deactivate.second.first;
it != deactivate.second.second;
++it)
it->deactivate();
SplitRange activate =
range_difference(new_beg, new_end, new_beg, deactivate.second.first);
// Note the use of the previously returned right range -------^
for (Iterator it = activate.second.first;
it != activate.second.second;
++it)
it->activate();
そして、そこに行きます。たぶん、この解決策はあなたの問題に対して少しやり過ぎかもしれませんが、このrange_difference
機能は多くの場所で役立つと思います.