Simple customized iterator with lambdas in C++
c++, containers, iterator, lambda
Solution
I suggest Boost's Transform Iterator. Here's an example usage:
#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);
}
I didn't quite get the part about custom `back_inserter`. If the type stored in `result` vector is the same as what the functor returns, the one from standard library will do. Otherwise you can just wrap it in `transform_iterator`, too.
Note that the functor is stored in a `std::function`. Boost relies on the functor to have a typedef `result_type` defined and lambdas don't have it.
Problem
Suppose I have a container which contains `int`, a function that works over containers containing `Point`, and that I have a function that given some `int` gives me the corresponding `Point` it represents (imagine that I have indexed all the points in my scene in some big `std::vector<Point>`). How do I create a simple (and efficient) wrapper to use my first container without copying its content? The code I want to type is something like that: ``` 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)); } }; ``` So, as you've seen, I'm looking for something a bit generic. I thought about using lambdas as well, but I'm getting a bit mixed up on how to proceed to keep it simple and user-friendly.