
Anatoli Tubman wrote:
John Torjo wrote:
However, had I used crange<int> r(d); // how do I know what iterators to keep inside? crange<int> r(v); // how do I know what iterators to keep inside?
You keep a pointer to crange_impl_base<int> which points to a heap-allocated instance of crange_impl<int, d_array>
Nope. :-)
Another option is to write
for (crange<int>& r = mkrange(d); r; ++r) { ... }
where mkrange returns crange_impl<int, d_array> which is derived from crange<int>.
This doesn't need heap allocation, but still needs virtual operator++ and virtual operator*.
Not that either. :-) With the FOREACH macro, you don't have to specify the container type, there is no heap allocation and no virtual function calls. Everything is fully-inline-able. And it doesn't need typeof. Anatoli is on the right track. Consider the following (typename left out for clarity): struct base {}; template<class T> struct derived : base { .... mutable T data; }; template<typename T> derived<T::iterator> begin( T &t ) { return derived<T::iterator>( t.begin(); ); } template<typename T> T::reference deref( base const &b, T & ) { return *static_cast< derived<T::iterator> const &>( b ).data; } ... std::vector<int> v( /*...*/ ); base const &b = begin( v ); int &i = deref( b, v ); ... Note the call to deref() above. Since you pass in the original container, its type is deduced and you can use that information to infer the actual type of the object refered to by "b". In this way, you only have to specify the element type, not the container type. -- Eric Niebler Boost Consulting www.boost-consulting.com