c ++大师:
有一些有用的c ++ stl算法,如find或search.但是,似乎他们只返回一个单一的交互者.
如果我想为STL容器做一个SQL样式'select'怎么办?比方说,一个矢量(可能会扩展到列表或地图).就像是
std::pair<vector::iterator, vector::iterator> select(std::vector::iterator begin, std::vector::iterator end, Comparor equal_to)
Run Code Online (Sandbox Code Playgroud)
输出应该是一个范围,类似于std :: pair,类似于boost :: multi-index中方法的返回值
在stl中有这样的东西吗?或者类似的任何可靠的图书馆?
你基本上有两种方法:
1)你在上面的注释中说的东西,将结果写入(迭代器指向)迭代器的容器.这看起来像这样:
template <typename ForwardIterator, typename OutputIterator, typename UnaryPredicate>
void select_iterators(ForwardIterator first, ForwardIterator last,
OutputIterator out, UnaryPredicate pred) {
while (first != last) {
if pred(*first) *out++ = first;
++first;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你称之为:
vector<Foo> myfoos;
vector<vector<Foo>::iterator> results;
select_iterators(myfoos.begin(), myfoos.end(), std::back_inserter(results), some_comparator);
Run Code Online (Sandbox Code Playgroud)
您实际上可以select_iterators使用copy_if和其他算法来定义boost::counting_iterator,但是当直接实现如此简单时,我认为这不值得.它看起来像:
template <typename ForwardIterator, typename OutputIterator, typename UnaryPredicate>
void select_iterators(ForwardIterator first, ForwardIterator last,
OutputIterator out, UnaryPredicate pred) {
std::copy_if(
boost::make_counting_iterator(first),
boost::make_counting_iterator(last),
out,
[&](ForwardIterator it) { return pred(*it); }
);
}
Run Code Online (Sandbox Code Playgroud)
2)不是预先测试所有值并在某处写入结果,而是定义一个迭代器,每次递增时都会在原始范围内前进,直到找到下一个匹配.Boost提供了两种方法,boost::filter_iterator并且boost::adaptors::filter.所以你可以写:
auto results = boost::adaptors::filter(myfoos, some_comparator);
Run Code Online (Sandbox Code Playgroud)
然后,无论你想对结果做什么,你都可以迭代results.begin()到results.end()它就像是一个容器.它不是容器,它不满足整个容器界面.它满足由Boost定义的接口,名为Range,相当于"可以迭代".它实际上只是一个过滤后的视图myfoos,因此不会Foo复制或移动任何对象.