所以,我想知道是否可以将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>
来调整适配器,只考虑输入向量中的特定值?
答案 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)
以从两个范围迭代器构造返回值。调用此构造函数比涉及推/插迭代器的解决方案更有效。