假设我有一个容器,其中包含int
,一个作用于包含以下内容的容器的函数Point
,并且我有一个函数可以给出一些int
给我相应的Point
它代表(想象一下我已经在一些大的场景中索引了场景中的所有点std::vector<Point>
)。如何创建一个简单(且高效)的包装器来使用我的第一个容器而不复制其内容?
我想要输入的代码是这样的:
template<typename InputIterator>
double compute_area(InputIterator first, InputIterator beyond) {
// Do stuff
}
template<typename InputIterator, typename OutputIterator>
void convex_hull(InputIterator first, InputIterator beyond, OutputIterator result) {
// Do stuff
}
struct Scene {
std::vector<Point> vertices;
foo(const std::vector<int> &polygon) {
// Create a simple wraper with limited amount of mumbo-jumbo
auto functor = [](int i) -> Point& { return vertices[polygon[i]]; });
MagicIterator polyBegin(0, functor);
MagicIterator polyEnd(polygon.size(), functor);
// NOTE: I want them to act as random access iterator
// And then use it directly
double a = compute_area(polyBegin, polyEnd);
// Bonus: create custom inserter similar to std::back_inserter
std::vector<int> result;
convex_hull(polyBegin, polyEnd, MagicInserter(result));
}
};
所以,正如你所看到的,我正在寻找一些通用的东西。我也考虑过使用 lambda,但我对如何继续保持简单和用户友好感到有点困惑。
我建议Boost 的变换迭代器 http://www.boost.org/doc/libs/1_54_0/libs/iterator/doc/transform_iterator.html。这是一个用法示例:
#include <boost/iterator/transform_iterator.hpp>
#include <vector>
#include <cassert>
#include <functional>
struct Point { int x, y; };
template<typename It>
void compute(It begin, It end)
{
while (begin != end) {
begin->x = 42;
begin->y = 42;
++begin;
}
}
int main()
{
std::vector<Point> vertices(5);
std::vector<int> polygon { 2, 3, 4 };
std::function<Point&(int)> functor = [&](int i) -> Point& { return vertices[i]; };
auto polyBegin = boost::make_transform_iterator(polygon.begin(), functor);
auto polyEnd = boost::make_transform_iterator(polygon.end(), functor);
compute(polyBegin, polyEnd);
assert(vertices[2].y == 42);
}
我不太明白有关定制的部分back_inserter
。如果类型存储在result
向量与函子返回的内容相同,标准库中的向量即可。否则你可以把它包裹起来transform_iterator
, too.
请注意,函子存储在std::function
。 Boost 依赖函子来拥有 typedefresult_type
已定义,而 lambda 没有它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)