【问题标题】:How to return an iterator_range如何返回 iterator_range
【发布时间】:2012-06-18 18:08:29
【问题描述】:

我想创建并保留一个 iterator_range。范围是基于谓词构造的(在本例中,我查找偶数)。

我可以这样做,但似乎我必须从正在迭代的底层向量中复制元素。

请在下面的示例中查找标记为“>>>”的 cmets。

有没有办法创建 iterator_range 而不必从原始向量创建条目的副本?

我看过,但还没有看到这种特殊情况的答案。

#include <vector>
#include <iostream>

#include <boost/bind.hpp>
#include <boost/range.hpp>
#include <boost/foreach.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/range/iterator_range.hpp>

using namespace std; 
using namespace boost; 

typedef boost::iterator_range<vector<int>::iterator> int_range;

template< class Range, class Pred >
boost::iterator_range< boost::filter_iterator< Pred, typename boost::range_iterator<Range>::type > > 
make_filter_range( Range& rng, Pred pred ) {
    return boost::make_iterator_range( 
     boost::make_filter_iterator(pred, boost::begin(rng), boost::end(rng)), 
     boost::make_filter_iterator(pred, boost::end(rng), boost::end(rng)) );
}

// This is the predicate evaluation function.
bool IsEvenFilter(int val) { return val % 2 == 0; }

void TestMakeIteratorRange()
{
    std::vector<int> vals;
    vals.push_back(1);
    vals.push_back(4);
    vals.push_back(7);
    vals.push_back(11);
    vals.push_back(16);
    vals.push_back(19);
    vals.push_back(28);

    //>>> The following int_range line does not compile.  Why?
    //>>> How can I return an int_range?
    //>>> int_range intRange = make_filter_range( vals, boost::bind(&IsEvenFilter, _1));

    //>>> The following WILL work, but it forces a second copy of elements from vals.
    std::vector<int> v2 = boost::copy_range< std::vector<int> >( 
        make_filter_range( vals, boost::bind(&IsEvenFilter, _1)));

    int_range intRange = int_range(v2);

    // Dump out contents
    BOOST_FOREACH(int &val, intRange)
    {
        cout << " " << val;
    }
    cout << endl;
}

void main()
{
    TestMakeIteratorRange();
}

【问题讨论】:

    标签: c++ boost iterator boost-range iterator-range


    【解决方案1】:
    int_range intRange = make_filter_range( vals, boost::bind(&IsEvenFilter, _1));
    

    您必须存储make_filter_range 返回的类型。 不是int_range

    这就是为什么 auto 存在的原因(在 C++11 中);因此,如果要存储函数返回的内容,则不必键入该返回值。如果您无权访问 C++11 auto,请改用 BOOST_AUTO

    如果由于某种原因您不能使用它,您也可以使用any_range.,顾名思义,它可以存储特定类型的任何范围。

    另外,请考虑使用proper Boost range-adapters,例如boost::adaptors::filtered,而不是make_filter_iterator

    【讨论】:

    • 非常感谢您的快速回复!我尝试了“自动”和 BOOST_AUTO。两者都有效。我有很多关于最佳 BOOST 用法的知识。它也有点复杂,因为我必须确保我想出的任何东西都适用于 Windows 和 Mac。再次感谢您的帮助。
    • @rcohn:如果这回答了您的问题,请单击绿色复选标记接受答案。
    • 好的。我点击了它。我很抱歉不知道这样做。这是我第一次发帖。
    猜你喜欢
    • 2021-12-08
    • 2019-06-26
    • 2018-09-10
    • 2016-07-21
    • 2012-06-24
    • 1970-01-01
    • 2012-10-29
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多