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

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

问题描述

我刚刚发现在某一时刻,C++11 草案对 std::pair 有 std::begin/std::end 重载 允许将一对迭代器视为适合在基于范围的 for 循环中使用的范围(N3126,第 20.3.5.5 节),但此后已被删除.

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:

  • 在基于范围的 for 循环中开始/结束的查找规则说开始/结束在 1) 作为范围对象的成员函数 2) 作为关联命名空间"中的自由函数进行查找
  • std::pair 没有开始/结束成员函数
  • 一般来说,std::pair 唯一关联的命名空间是命名空间 std
  • 我们不能为std::pair自己重载std::begin/std::end
  • 我们不能为 std::pair 特化 std::begin/std::end (因为特化必须是部分的这在函数中是不允许的)
  • 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?

推荐答案

我认为 2009 年的论文 "对不构成好的范围" Alisdair Meredith 至少是答案的一部分.基本上,许多算法返回实际上不能保证是有效范围的迭代器对.由于这个原因,他们似乎从 for-range 循环中删除了对 pair 的支持.然而,所提出的解决方案并未被完全采纳.

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.

如果您确定某对迭代器确实代表了一个有效范围,那么您可以将它们包装成一个提供 begin()/end() 成员函数的自定义类型:

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

(未经测试)

我同意这有点棘手.返回有效范围的函数(如equal_range)应该使用适当的返回类型来说明.有点尴尬,我们必须通过上面的 as_range 之类的东西手动确认这一点.

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天全站免登陆