C++ 11中是否有一个范围类用于基于范围的循环?

Omn*_*ous 99 c++ std c++11

我发现自己刚刚写了这篇文章:

template <long int T_begin, long int T_end>
class range_class {
 public:
   class iterator {
      friend class range_class;
    public:
      long int operator *() const { return i_; }
      const iterator &operator ++() { ++i_; return *this; }
      iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }

      bool operator ==(const iterator &other) const { return i_ == other.i_; }
      bool operator !=(const iterator &other) const { return i_ != other.i_; }

    protected:
      iterator(long int start) : i_ (start) { }

    private:
      unsigned long i_;
   };

   iterator begin() const { return iterator(T_begin); }
   iterator end() const { return iterator(T_end); }
};

template <long int T_begin, long int T_end>
const range_class<T_begin, T_end>
range()
{
   return range_class<T_begin, T_end>();
}
Run Code Online (Sandbox Code Playgroud)

这允许我写这样的东西:

for (auto i: range<0, 10>()) {
    // stuff with i
}
Run Code Online (Sandbox Code Playgroud)

现在,我知道我写的可能不是最好的代码.也许有一种方法可以使它更灵活和有用.但在我看来,像这样的东西应该成为标准的一部分.

它也是吗?是否在一系列整数上为迭代器添加了某种新库,或者可能是通用范围的计算标量值?

Nic*_*las 58

C++标准库没有,但是Boost.Range有boost :: counting_range,它肯定有资格.你也可以使用boost :: irange,它在范围上更有针对性.

C++ 20的范围库将允许您通过view::iota(start, end).

  • 最近取得了很大进展,以达到标准范围(N4128).有关提案和参考实现,请参阅https://github.com/ericniebler/range-v3. (6认同)
  • 是的,这绝对是我要寻找的本质.我很高兴Boost做到了.我很遗憾标准委员会不管出于何种原因都不包括它.它将成为范围基础功能的一个很好的补充. (3认同)

Naw*_*waz 47

据我所知,C++ 11中没有这样的类.

无论如何,我试图改进你的实现.我把它设为非模板,因为我认为制作模板没有任何优势.相反,它有一个主要缺点:您无法在运行时创建范围,因为您需要在编译时知道模板参数.

//your version
auto x = range<m,n>(); //m and n must be known at compile time

//my version
auto x = range(m,n);  //m and n may be known at runtime as well!
Run Code Online (Sandbox Code Playgroud)

这是代码:

class range {
 public:
   class iterator {
      friend class range;
    public:
      long int operator *() const { return i_; }
      const iterator &operator ++() { ++i_; return *this; }
      iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }

      bool operator ==(const iterator &other) const { return i_ == other.i_; }
      bool operator !=(const iterator &other) const { return i_ != other.i_; }

    protected:
      iterator(long int start) : i_ (start) { }

    private:
      unsigned long i_;
   };

   iterator begin() const { return begin_; }
   iterator end() const { return end_; }
   range(long int  begin, long int end) : begin_(begin), end_(end) {}
private:
   iterator begin_;
   iterator end_;
};
Run Code Online (Sandbox Code Playgroud)

测试代码:

int main() {
      int m, n;
      std::istringstream in("10 20");
      if ( in >> m >> n ) //using in, because std::cin cannot be used at coliru.
      {
        if ( m > n ) std::swap(m,n); 
        for (auto i : range(m,n)) 
        {
             std::cout << i << " ";
        }
      }
      else 
        std::cout <<"invalid input";
}
Run Code Online (Sandbox Code Playgroud)

输出:

10 11 12 13 14 15 16 17 18 19

Onine演示.

  • @Nawaz:我仍然在整数类型上模板化它:)我还建议将`iterator`别名改为`const_iterator`,让`iterator`派生自`std :: iterator`并让`range`实现` cbegin`和`cend`.哦,...为什么`iterator :: operator ++`返回一个*const*引用? (10认同)
  • @RedX:[Dijkstra](http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html)对于为什么范围标记最好为"[开始,结束]"有一个很好的记录`.@OP:基于范围的循环的双关语+1,不是双关语:-) (6认同)
  • 我喜欢.我想过一个非模板版本.而且我认为一个好的编译器会在值实际上是恒定的情况下很好地优化它.我得测试一下. (3认同)
  • 非模板版本的优点是在编译时不需要知道循环的长度.当然,你可以使整数类型模板化. (2认同)
  • @weeska:该重载应该实现后缀增量"v ++",它应该在增量操作发生之前返回值*.我建议你去探索`++ i`和`i ++`之间的区别,其中`i`被声明为`int`. (2认同)

Ara*_*raK 13

我编写了一个名为range完全相同目的的库,除了它是一个运行时范围,我的案例中的想法来自Python.我认为是一个编译时版本,但在我看来,获得编译时版本并没有什么好处.您可以在bitbucket上找到该库,它位于Boost License:Range下.它是一个单头库,与C++ 03兼容,并且像C++ 11中的基于范围的for循环一样有魅力:)

特点:

  • 一个真正的随机访问容器,所有的铃声和​​口哨声!

  • 范围可以按字典顺序进行比较.

  • 两个函数exist(返回bool)和find(返回迭代器)来检查数字是否存在.

  • 该库使用CATCH进行单元测试.

  • 基本用法示例,使用标准容器,使用标准算法并使用基于范围的for循环.

这是一分钟的介绍.最后,我欢迎任何有关这个小型图书馆的建议.