Kind of, but not really.
You want to access data sequentially when you don't know how it's stored. You have three options:
- Copy the data into a container with known format (the "return vector" option).
- Use compile-time polymorphism to choose the correct access method (the way std algorithms do it, not possible due to you using an interface).
- Use runtime polymorphism to choose the correct access method.
So the second is not possible due to the constraint that you want to use an interface. The first and the third both come with overhead.
The obvious way of doing the third thing is any_range
. But it's not the only way, depending on what you want to do. The problem with any_range
is that in a simple for-each loop, there are three virtual calls for every element: the increment, the comparison, and the dereference.
As long as all you want to do is simple for-each iteration, you could reduce the overhead to one virtual call by implementing the loop on the interface level:
struct Interface {
Interface(SomeType& other)
: traverse([=](std::function<void(int)> body) {
for (int i : other.my_range()) body(i);
}) {}
const std::function<void (std::function<void(int)>)> traverse;
};
Of course that only works as long as the ways you use the range are very limited.