I’ve implemented something like this before, without macros. It’s a little ugly, but not that bad IMO.
If you write a native range-based for loop:
for (auto foo : obj) { /* do something */ }
it essentially desugars to auto it = foo.begin();
auto end = foo.end();
for (; it != end; ++it) {
auto foo = *it;
/* do something */
}
To make it work with a custom type, you need to implement `begin()` and `end()` methods, but the returned objects don’t need to support the full STL iterator protocol; they only need to support the exact sequence of operations from the desugaring. So, for example, `end()` can return a unique `End` type that contains no data and does nothing. `begin()` can return a different type that does all the real work and implements `operator!=(End)`. With that, it’s not too hard to implement a wrapper around a Python-like iterator protocol.The main drawback is that you need to temporarily store each item in the begin object before it’s moved into the iteration variable. This is because you have to already know whether a next item exists at the point of `it != end`, but then the item isn’t actually retrieved until `*it`. The extra move has a slight cost, but the compiler can often optimize it away to nothing. You can also avoid this if the for loop uses a reference type (`for (auto& foo : obj)`).