我刚刚发现,在某一时刻,C ++ 11草案对std::begin
的{{1}} / std::end
重载允许将一对迭代器视为适合在基于范围的for循环(N3126,第20.3.5.5节),但此后已被删除。
有谁知道它被删除的原因?
我发现删除非常不幸,因为似乎没有其他方法可以将一对迭代器视为范围。事实上:
std::pair
没有开始/结束成员函数std::pair
唯一关联的命名空间通常是namespace std std::pair<T, U>
/ std::begin
为std::end
自己重载std::pair
专门化std::begin
/ std::end
(因为专业化必须是部分的,而且不允许使用函数)我还有其他方法吗?
答案 0 :(得分:40)
我认为Alisdair Meredith撰写的2009年论文"Pairs do not make good ranges"至少是答案的一部分。基本上,许多算法返回的迭代器对实际上并不保证是有效范围。由于这个原因,他们似乎从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
手动确认这一点,这有点令人尴尬。
答案 1 :(得分:6)
使用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;
}