如何使我的自定义类型使用“基于范围的for循环”?

如何使我的自定义类型使用“基于范围的for循环”?

像现在很多人一样,我一直在尝试C+11带来的不同特性。我最喜欢的一个是“基于范围的循环”。

我知道:

for(Type& v : a) { ... }

相当于:

for(auto iv = begin(a); iv != end(a); ++iv){
  Type& v = *iv;
  ...}

而那begin()简单地返回a.begin()标准容器。

但如果我想使我的自定义类型“基于范围的for循环”-感知 ?

我是不是应该专攻begin()end() ?

如果我的自定义类型属于命名空间xml,我是否应该定义xml::begin()std::begin() ?

简言之,这方面的指引是甚麽?


慕桂英4014372
浏览 645回答 3
3回答

郎朗坤

标准的相关部分为6.5.4/1:如果_RangeT是类型,则在class_RangeT的范围内查找unqualified-id开始和结束,就好像通过类成员访问查找(3.4.5)一样,并且如果其中一个(或两者都)finds至少有一个声明、BEG-Exr和End-Exr是__range.begin()和__range.end()分别;-否则,开始-支出和结束-费用是begin(__range)和end(__range),分别使用依赖于参数的查找(3.4.2)查找开始和结束的位置。出于这个名称查找的目的,命名空间std是一个关联的命名空间。因此,您可以执行以下任何操作:定义begin和end成员函数定义begin和endADL将找到的免费函数(简化版本:将它们与类放在同一个名称空间中)专门性std::begin和std::endstd::begin调用begin()成员函数,所以如果您只实现上面的一个,那么不管您选择哪一个,结果都应该是相同的。对于基于范围的for循环来说,这是相同的结果,对于没有自己神奇的名称解析规则的凡间代码也是如此。using std::begin;然后是一个无条件的呼叫begin(a).如果您实现了成员函数和然而,ADL函数,则基于范围的for循环应该调用成员函数,而只有凡人才会调用ADL函数。最好确保他们在这种情况下做同样的事情!如果您正在编写的东西实现了容器接口,那么它将有begin()和end()成员函数已经完成,这应该足够了。如果它不是一个容器的范围(如果它是不可变的,或者如果您不知道前面的大小),那么您可以自由选择。在您列出的选项中,请注意绝不能过载std::begin()..您可以为用户定义的类型专门化标准模板,但除此之外,向命名空间std添加定义是未定义的行为。但是无论如何,专门化标准函数是一个糟糕的选择,因为缺少部分函数专门化意味着您只能对单个类进行专门化,而不能对类模板进行专门化。

炎炎设计

我写我的答案是因为有些人可能更喜欢简单的现实生活中没有STL包含的例子。出于某种原因,我有自己的纯数据数组实现,我想使用基于范围的for循环。这是我的解决方案:&nbsp;template&nbsp;<typename&nbsp;DataType> &nbsp;class&nbsp;PodArray&nbsp;{ &nbsp;public: &nbsp;&nbsp;&nbsp;class&nbsp;iterator&nbsp;{ &nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator(DataType&nbsp;*&nbsp;ptr):&nbsp;ptr(ptr){} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;operator++()&nbsp;{&nbsp;++ptr;&nbsp;return&nbsp;*this;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;operator!=(const&nbsp;iterator&nbsp;&&nbsp;other)&nbsp;const&nbsp;{&nbsp;return&nbsp;ptr&nbsp;!=&nbsp;other.ptr;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;DataType&&nbsp;operator*()&nbsp;const&nbsp;{&nbsp;return&nbsp;*ptr;&nbsp;} &nbsp;&nbsp;&nbsp;private: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataType*&nbsp;ptr; &nbsp;&nbsp;&nbsp;}; &nbsp;private: &nbsp;&nbsp;&nbsp;unsigned&nbsp;len; &nbsp;&nbsp;&nbsp;DataType&nbsp;*val; &nbsp;public: &nbsp;&nbsp;&nbsp;iterator&nbsp;begin()&nbsp;const&nbsp;{&nbsp;return&nbsp;iterator(val);&nbsp;} &nbsp;&nbsp;&nbsp;iterator&nbsp;end()&nbsp;const&nbsp;{&nbsp;return&nbsp;iterator(val&nbsp;+&nbsp;len);&nbsp;} &nbsp;&nbsp;&nbsp;//&nbsp;rest&nbsp;of&nbsp;the&nbsp;container&nbsp;definition&nbsp;not&nbsp;related&nbsp;to&nbsp;the&nbsp;question&nbsp;... &nbsp;};然后是用法示例:PodArray<char>&nbsp;array;//&nbsp;fill&nbsp;up&nbsp;array&nbsp;in&nbsp;some&nbsp;wayfor(auto&&nbsp;c&nbsp;:&nbsp;array) &nbsp;&nbsp;printf("char:&nbsp;%c\n",&nbsp;c);
打开App,查看更多内容
随时随地看视频慕课网APP