Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2004-04-22 11:04:28

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

Boost list run by bdawes at, gregod at, cpdaniel at, john at