ある時点で、C++ 11ドラフトにstd::begin
のstd::end
/std::pair
オーバーロードがあり、イテレータのペアを範囲での使用に適した範囲として扱うことができることを発見しました- forループ(N3126、セクション20.3.5.5)に基づいていますが、これはその後削除されました。
なぜ削除されたのか誰か知っていますか?
イテレータのペアを範囲として扱う方法は他にないように思われるため、削除は非常に残念です。確かに:
std::pair
には開始/終了メンバー関数がありませんstd::pair<T, U>
に関連付けられている名前空間はnamespacestdのみです。std::begin
のためにstd::end
/std::pair
をオーバーロードすることは許可されていませんstd::begin
/std::end
をstd::pair
に特化することはできません(特殊化は部分的である必要があり、関数では許可されていないため)私が行方不明になっている他の方法はありますか?
私は2009年の論文 「ペアは良い範囲を作らない」 AlisdairMeredithによると少なくとも答えの一部だと思います。基本的に、多くのアルゴリズムは、実際には有効な範囲であることが保証されていないイテレータのペアを返します。このため、for-rangeループからpair<iterator,iterator>
のサポートが削除されたようです。しかし、提案された解決策は完全には採用されていません。
イテレータのいくつかのペアが実際に有効な範囲を表すことが確実にわかっている場合は、begin()/ end(を提供するカスタム型にそれらをラップできます。 )メンバー関数:
template<class Iter>
struct iter_pair_range : std::pair<Iter,Iter> {
iter_pair_range(std::pair<Iter,Iter> const& x)
: std::pair<Iter,Iter>(x)
{}
Iter begin() const {return this->first;}
Iter end() const {return this->second;}
};
template<class Iter>
inline iter_pair_range<Iter> as_range(std::pair<Iter,Iter> const& x)
{ return iter_pair_range<Iter>(x); }
int main() {
multimap<int,int> mm;
...
for (auto& p : as_range(mm.equal_range(42))) {
...
}
}
(未テスト)
私はこれが少し疣贅であることに同意します。有効な範囲(equal_rangeなど)を返す関数は、適切な戻り値の型を使用してそのように言う必要があります。上記のas_range
のような方法でこれを手動で確認する必要があるのは少し恥ずかしいことです。
_boost::make_iterator_range
_を使用できます。 begin()
およびend()
メソッドを使用してiterator_rangeを構築します。 _boost::make_iterator_range
_は_std::pair
_のイテレータを受け入れることができます。
c ++ 11最適化を使用して、上記の回答を拡張します。
#include <utility>
template<class Iter>
struct range_t : public std::pair<Iter, Iter> {
using pair_t = std::pair<Iter, Iter>;
range_t(pair_t&& src)
: std::pair<Iter, Iter>(std::forward<pair_t>(src))
{}
using std::pair<Iter, Iter>::first;
using std::pair<Iter, Iter>::second;
Iter begin() const { return first; }
Iter end() const { return second; }
};
template<class Iter>
range_t<Iter> range(std::pair<Iter, Iter> p) {
return range_t<Iter>(std::move(p));
}
template<class Iter>
range_t<Iter> range(Iter i1, Iter i2) {
return range_t<Iter>(std::make_pair(std::move(i1), std::move(i2)));
}
// TEST:
#include <iostream>
#include <set>
using namespace std;
int main() {
multiset<int> mySet { 6,4,5,5,5,3,3,67,8,89,7,5,45,4,3 };
cout << "similar elements: ";
for (const auto&i : range(mySet.lower_bound(5), mySet.upper_bound(10))) {
cout << i << ",";
}
cout << "\n";
int count = 0, sum = 0;
for (const auto& i: range(mySet.equal_range(5)))
{
++count;
sum += i;
}
cout << "5 appears " << count << " times\n"
<< "the sum is " << sum << "\n";
return 0;
}