为什么从C ++ 11中删除对范围访问?
我刚刚发现,C ++ 11草案有一个std::begin
/ std::end
重载std::pair
,允许将一对迭代器视为适合在基于范围的for循环中使用的范围(N3126,第20.3.5.5节),但是这已经被删除。
有谁知道为什么它被删除?
我发现删除非常不幸,因为它似乎没有其他的方式来处理一对迭代器作为范围。 确实:
- 在基于范围的for循环中,begin / end的查找规则表示在1)中将begin / end作为范围对象的成员函数2)作为“关联名称空间”中的自由函数进行查找
-
std::pair
没有开始/结束成员函数 -
std::pair<T, U>
唯一相关的命名空间通常是命名空间std - 我们不允许自己为
std::pair
加载std::begin
/std::end
- 我们不能将
std::begin
/std::end
专门化为std::pair
(因为专精必须是部分的,而且不允许用于函数)
有没有其他的方式,我失踪了?
我认为阿里斯代尔梅雷迪斯(Alisdair Meredith)2009年发表的文章“对不做好范围”至less是答案的一部分。 基本上,许多algorithm返回实际不能保证是有效范围的迭代器对。 看来他们从for-range循环中移除了pair<iterator,iterator>
的支持。 但是,提出的解决scheme还没有完全采用。
如果您确定某些迭代器对确实代表有效范围,那么您可以将它们封装到提供begin()/ end()成员函数的自定义types中:
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)应该这样说,使用适当的返回types。 有点不好意思,我们不得不通过类似上面的as_range
手动确认。
你可以使用boost::make_iterator_range
。 它用begin()
和end()
方法构造一个iterator_range。 boost::make_iterator_range
可以接受std::pair
iterator 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; }