为什么从C ++ 11中删除对范围访问? [英] Why was pair range access removed from C++11?

查看:140
本文介绍了为什么从C ++ 11中删除对范围访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发现有一点,C ++ 11草稿有 std :: begin / std :: end 重载 std :: pair 允许将一对迭代器视为适合在基于范围的for循环中使用的范围(N3126,第20.3.5.5节)



有人知道为什么会被移除吗?



非常不幸,因为它似乎没有其他方法来对待一对迭代器作为一个范围。确实:




  • 在基于范围的for循环中,begin / end的查找规则表示begin / end是在1)范围对象的成员函数2)作为关联命名空间中的自由函数

  • std :: pair 没有begin / end成员函数

  • std :: pair< T,U> 的唯一关联命名空间通常是namespace std

  • 我们不允许重载 std :: begin / std :: end c $ c> std :: pair 自己

  • 我们不能专注于 std :: begin / std :: end std :: pair (因为专业化将必须是部分的, / li>


有没有其他方法我缺少?

解决方案

我认为2009年的文章对不做好范围 Alisdair Meredith至少是答案的一部分。基本上,许多算法返回实际上不能保证为有效范围的迭代器对。似乎他们从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 手动确认这一点。


I just discovered that at one point, the C++11 draft had std::begin/std::end overloads for std::pair that allowed treating a pair of iterators as a range suitable for use in a range-based for loop (N3126, section 20.3.5.5), but this has since been removed.

Does anyone know why it was removed?

I find the removal very unfortunate, because it seems there is no other way to treat a pair of iterators as a range. Indeed:

  • The lookup rules for begin/end in a range-based for loop say that begin/end are looked for in 1) as member functions of the range object 2) as free functions in "associated namespaces"
  • std::pair does not have begin/end member functions
  • The only associated namespace for std::pair<T, U> in general is namespace std
  • We are not allowed to overload std::begin/std::end for std::pair ourselves
  • We cannot specialize std::begin/std::end for std::pair (because the specialization would have to be partial and that's not allowed for functions)

Is there some other way that I am missing?

解决方案

I think the 2009 paper "Pairs do not make good ranges" by Alisdair Meredith is at least part of the answer. Basically, many algorithms return pairs of iterators that are actually not guaranteed to be valid ranges. It seems they removed the support for pair<iterator,iterator> from the for-range loop for this reason. However, the proposed solution has not been fully adopted.

If you know for certain that some pair of iterators really represents a valid range then you could wrap them into a custom type which offers begin()/end() member functions:

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))) {
       ...
    }
}

(untested)

I agree this is a bit of a wart. Functions which return valid ranges (like equal_range) should say so using an appropriate return type. It's a bit embarrasing that we have to manually confirm this via something like as_range above.

这篇关于为什么从C ++ 11中删除对范围访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆