2

iterator_range を作成して保持したいと思います。範囲は、述語に基づいて構築されます (この例では、偶数を探します)。

私はこれを行うことができますが、反復されている基になるベクトルから要素をコピーする必要があるようです。

以下のサンプルで ">>>" とマークされたコメントを探してください。

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();
}
4

1 に答える 1

4
int_range intRange = make_filter_range( vals, boost::bind(&IsEvenFilter, _1));

You have to store the type returned by make_filter_range. Which is not int_range.

This is incidentally why auto exists (in C++11); so that you don't have to type that return value if you want to store what the function returns. If you don't have access to C++11 auto, use BOOST_AUTO instead.

If you can't use that for some reason, you can also use any_range. Which, as the name suggests, can store any range for a specific type.

Also, consider using the proper Boost range-adapters, like boost::adaptors::filtered instead of make_filter_iterator.

于 2012-06-15T16:35:09.463 に答える