Boost logo

Boost :

From: John Torjo (john.lists_at_[hidden])
Date: 2004-04-23 03:08:52


John Torjo wrote:

> David Abrahams wrote:
>
>> John Torjo <john.lists_at_[hidden]> writes:
>>
>>
>>
>>>> time, you don't have to name the element type ;-)
>>>>
>>>>
>>>>
>>>>
>>>
>>> of course ;) the element type is deduced from the container type.
>>> For instance, if you want a constant range, just do:
>>> crange<const container> r(cont);
>>> //... etc
>>>
>>
>>
>> But container is usually "spelt something<element_type>", so I'd pick
>> naming the element type over naming the container type any day.
>>
>>
>>
> But it's technically not possible.

Actually, I was wrong. You can get away, without knowing the container type.
Here's a small example (tested on vc7.1):

You can actually do:
    for( crange<int> const & r = mkrange(v); r; ++r)
        std::cout << "from v " << *r << std::endl;
    for( crange<int> const & r = mkrange(l); r; ++r)
        std::cout << "from l " << *r << std::endl;

template< class type, class container> struct crange_impl;

template< class type> struct crange {
protected:
    typedef crange<type> self_type;
    typedef void (*incrementer)(const self_type&);
    typedef bool (*at_end)(const self_type &);
    typedef type & (*deref)(const self_type&);

    crange( incrementer inc_func, at_end at_end_func, deref deref_func)
        : m_inc_func(inc_func), m_at_end_func(at_end_func),
m_deref_func(deref_func) {}
public:

    operator bool() const { return !m_at_end_func(*this); }
    const self_type & operator++() const { m_inc_func(*this); return
*this; }
    type & operator*() const { return m_deref_func(*this); }
private:
    incrementer m_inc_func;
    at_end m_at_end_func;
    deref m_deref_func;
};

template< class type, class container> struct crange_impl : public
crange<type> {
    typedef crange<type> base;
    typedef crange_impl<type,container> self_type;
    crange_impl( container & c) : m_first(c.begin()), m_last(c.end()),
        base(&self_type::increment, &self_type::at_end,
&self_type::deref) {}

private:
    static void increment(const base & me) {
        const self_type & self = reinterpret_cast<const self_type&>(me);
        ++self.m_first;
    }
    static bool at_end(const base & me) {
        const self_type & self = reinterpret_cast<const self_type&>(me);
        return self.m_first == self.m_last;
    }
    static type & deref(const base & me) {
        const self_type & self = reinterpret_cast<const self_type&>(me);
        return *self.m_first;
    }
private:
    mutable typename container::iterator m_first, m_last;
};

template<class container> crange_impl<typename container::value_type,
container> mkrange(container & c) {
    typedef crange_impl<typename container::value_type, container> impl;
    return impl(c);
}

#include <vector>
#include <list>
#include <algorithm>
int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> v;
    std::list<int> l;
    v.push_back(1); v.push_back(5); v.push_back(7); v.push_back(9);
    std::copy( v.begin(), v.end(), std::back_inserter(l));
    v.push_back(11); v.push_back(25); v.push_back(37); v.push_back(69);

    for( crange<int> const & r = mkrange(v); r; ++r)
        std::cout << "from v " << *r << std::endl;
    for( crange<int> const & r = mkrange(l); r; ++r)
        std::cout << "from l " << *r << std::endl;
    return 0;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk