STL或boost中的C++范围/ xrange等价物?

Any*_*orn 37 c++ boost iterator

在STL或boost中是否有C++等效的python Xrange生成器?

xrange基本上生成递增的数字,每次调用++运算符.构造函数是这样的:

xrange(first, last, increment)
Run Code Online (Sandbox Code Playgroud)

我希望通过每个使用boost来做这样的事情:

foreach(int i, xrange(N))
Run Code Online (Sandbox Code Playgroud)

我知道for循环.在我看来,他们是太多的样板.

谢谢

我的理由:

我想要这样做的主要原因是因为我使用语音文本软件,并且编程循环通常很难,即使使用代码完成.具有可显示的构造更有效.

许多循环从零开始并递增1,这是范围的默认值.我发现python构造更直观

 for(int i = 0; i < N; ++i)
 foreach(int i, range(N))
Run Code Online (Sandbox Code Playgroud)

需要将范围作为参数的函数:

 Function(int start, int and, int inc);
 function(xrange r);
Run Code Online (Sandbox Code Playgroud)

我理解语言之间的差异,但是如果python中的特定构造对我非常有用并且可以在C++中高效实现,我没有理由不使用它.对于每个构造,C++都是外来的,但是人们使用它.

我将我的实现放在页面底部以及示例用法.

在我的域中我使用多维数组,通常排名4张量.所以我经常会得到4个具有不同范围/增量的嵌套循环来计算规范化,索引等等.这些不一定是性能循环,我更关心正确性可读性和修改能力.

例如

int function(int ifirst, int ilast, int jfirst, int jlast, ...);
versus
int function(range irange, range jrange, ...);
Run Code Online (Sandbox Code Playgroud)

在上面,如果需要不同的strid,你必须传递更多的变量,修改循环等,最终你会得到大量的整数/几乎相同的循环.

foreach和range完全解决了我的问题.对普通C++程序员的熟悉程度并不高我的关注列表 - 问题领域是一个相当模糊,有很多元编程,SSE内在,生成代码.

seh*_*ehe 52

提升伊兰奇应该是答案(ThxPaul Brannan)

我正在添加我的答案,以提供一个 非常 有效的用例的令人信服的例子,这些用例通过手动循环无法很好地完成:

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/irange.hpp>

using namespace boost::adaptors;

static int mod7(int v) 
    { return v % 7; }

int main() 
{
    std::vector<int> v;

    boost::copy(
            boost::irange(1,100) | transformed(mod7), 
            std::back_inserter(v));

    boost::sort(v);

    boost::copy(
            v | reversed | uniqued, 
            std::ostream_iterator<int>(std::cout, ", "));
}
Run Code Online (Sandbox Code Playgroud)

输出:6, 5, 4, 3, 2, 1, 0,

注意这类似于生成器/理解(函数语言)和可枚举(C#)

更新我以为我会提到C++ 11允许的以下(非常不灵活)的习语:

for (int x : {1,2,3,4,5,6,7})
    std::cout << x << std::endl;
Run Code Online (Sandbox Code Playgroud)

当然你可以嫁给它irange:

for (int x : boost::irange(1,8))
    std::cout << x << std::endl;
Run Code Online (Sandbox Code Playgroud)

  • 我改变你的答案使用`boost :: irange`而不是`boost :: make_integer_range`.我希望你不介意;) (2认同)

Unc*_*ens 20

据我所知,Boost有counting_iterator,它似乎只允许以1为增量递增.对于完整的xrange功能,你可能需要自己实现一个类似的迭代器.

总而言之,它可能看起来像这样(编辑:为xrange的第三个重载添加了一个迭代器,以使用boost的迭代器外观):

#include <iostream>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/foreach.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <cassert>

template <class T>
boost::iterator_range<boost::counting_iterator<T> > xrange(T to)
{
    //these assertions are somewhat problematic:
    //might produce warnings, if T is unsigned
    assert(T() <= to);
    return boost::make_iterator_range(boost::counting_iterator<T>(0), boost::counting_iterator<T>(to));
}

template <class T>
boost::iterator_range<boost::counting_iterator<T> > xrange(T from, T to)
{
    assert(from <= to);
    return boost::make_iterator_range(boost::counting_iterator<T>(from), boost::counting_iterator<T>(to));
}

//iterator that can do increments in steps (positive and negative)
template <class T>
class xrange_iterator:
    public boost::iterator_facade<xrange_iterator<T>, const T, std::forward_iterator_tag>
{
    T value, incr;
public:
    xrange_iterator(T value, T incr = T()): value(value), incr(incr) {}
private:
    friend class boost::iterator_core_access;
    void increment() { value += incr; }
    bool equal(const xrange_iterator& other) const
    {
        //this is probably somewhat problematic, assuming that the "end iterator"
        //is always the right-hand value?
        return (incr >= 0 && value >= other.value) || (incr < 0 && value <= other.value);
    }
    const T& dereference() const { return value; }
};

template <class T>
boost::iterator_range<xrange_iterator<T> > xrange(T from, T to, T increment)
{
    assert((increment >= T() && from <= to) || (increment < T() && from >= to));
    return boost::make_iterator_range(xrange_iterator<T>(from, increment), xrange_iterator<T>(to));
}

int main()
{
    BOOST_FOREACH(int i, xrange(10)) {
        std::cout << i << ' ';
    }
    BOOST_FOREACH(int i, xrange(10, 20)) {
        std::cout << i << ' ';
    }
    std::cout << '\n';
    BOOST_FOREACH(int i, xrange(0, 46, 5)) {
        std::cout << i << ' ';
    }
    BOOST_FOREACH(int i, xrange(10, 0, -1)) {
        std::cout << i << ' ';
    }
}
Run Code Online (Sandbox Code Playgroud)

正如其他人所说的那样,我不认为这会比正常的循环更能吸引你.