|
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