
John Torjo wrote:
David Abrahams wrote:
John Torjo <john.lists@torjo.com> 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; }