在容器排列中使用C ++适配器和库函数对象

时间:2018-06-04 10:37:46

标签: c++ stl

所以,我想知道是否可以将C ++适配器与库函数对象结合起来,以便对C ++标准库中定义的容器进行一些操作。

例如,如果我要定义带有一些元素的向量

vector<int> vi={1,2,3,4,5,6,7,8,9,0};

并且我只想计算该向量中包含的值大于例如4的值,我对使用适配器的可能性感兴趣:

priority_queue<int, vector<int>, greater<int> > pq(vi.begin(),vi.end());

但是,在我看来,前一行只会将vi的完整副本复制到pq,同时考虑到元素顺序是递增的。有没有办法通过greater<int>来调整适配器,只考虑输入向量中的特定值?

2 个答案:

答案 0 :(得分:3)

Eric Niebler的ranges library有很多适应范围的设施,特别是过滤范围。但是,标准库容器本身不允许这样的适配器。如果你没有迭代器对而不是范围,并且想要避免需要Concept支持,那么Boost库有很多迭代器实用程序代码:Boost Iterator Library,包括boost::filter_iterator

话虽如此,您可以使用标准库工具(例如std::copy_if)轻松地使用过滤从旧容器初始化新容器:

template< class InputIt, class OutputIt, class UnaryPredicate >
constexpr OutputIt copy_if( InputIt first, InputIt last,
                            OutputIt d_first,
                            UnaryPredicate pred );

在你的情况下,它会是这样的:

std::priority_queue<int, std::vector<int>, std::greater<int> > pq;
auto greater_than_four = [](int x) { return x > 4; };
std::copy_if(vi.begin(), vi.end(), push_insert_iterator(pq), greater_than_four);

push_insert_iterator定义here。 (代码未经测试。)

答案 1 :(得分:3)

您可以使用boost::filter_iterator过滤输入容器的元素:

#include <boost/iterator/filter_iterator.hpp>
#include <queue>
#include <vector>

int main() {
    using namespace std;
    vector<int> vi={1,2,3,4,5,6,7,8,9,0};
    auto filter = [](int a) { return a > 5; };
    priority_queue<int, vector<int>, greater<int>> pq(
        boost::make_filter_iterator(filter, vi.begin(), vi.end()),
        boost::make_filter_iterator(filter, vi.end(), vi.end())
        );
}

或者,使用boost::range library语法更简洁:

#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <queue>
#include <vector>

int main() {
    using namespace std;
    vector<int> vi={1,2,3,4,5,6,7,8,9,0};
    auto filter = [](int a) { return a > 4; };
    using C = priority_queue<int, vector<int>, greater<int>>;
    C pq = boost::copy_range<C>(vi | boost::adaptors::filtered(filter));
}

引擎盖boost::copy_range<Sequence>(...)执行return Sequence(begin, end)以从两个范围迭代器构造返回值。调用此构造函数比涉及推/插迭代器的解决方案更有效。