wrapper to add Boost.Iterator adaptors to Boost.Range

I've worked up a subclass that adds Boost.Iterator functionality to a Boost.Range object. The motivation was twofold: Range combines begin() and end() into one object, preventing the need to write iterator adapter code twice, and adding adaptors into the subclass avoids the need to specify namespaces and allows code structures similar to those of perl or ruby. I expect that this type of writing will become desirable when C++0x lambda functions are available. The C++0x 'auto' keyword will allow storing the generated iterators to local variables for further arithmetic; as it stands now the induced types are far to complex to be written out by hand. The point of this message is just to share the idea in case anyone wishes to do something with it. I'm relatively new to C++ and lack the knowledge needed to make something like this the right way. For example, I have no idea how to make the transform_tuple function work with anything other than a two element tuple. The '*' and '+' arithmetic operators have been defined to perform pairwise arithmetic between elements, but it may also make sense to define operators like "magic_iter + scalar" and "magic_iter += magic_iter". With the 'auto' keyword this would allow converting a bunch of STL containers into iterator objects which could then be manipulated mathematically as if they were Blitz++ arrays. /////////////////////////////////////////////// // magic_iter_demo.cpp /////////////////////////////////////////////// #include <magic_iter.h> #include <vector> #include <set> #include <iostream> #include <boost/foreach.hpp> #include <boost/lambda/lambda.hpp> using namespace boost::lambda; int main() { std::cout << "--- odd multiples of 10, reverse sorted\n"; std::vector<int> tmp; BOOST_FOREACH( int x, my::make_magic_counter(0, 10). filter(_1 & 1). transform<int>(_1 * 10). assign_to(tmp). // needed to allow sort sort(_1 > _2) ) { std::cout << x << std::endl; } std::cout << "--- unique elements of v*w, using zip\n"; std::vector<int> v; std::vector<double> w; my::make_magic_counter(0, 11). transform<int>(_1 - 5). assign_to(v). transform<double>(_1 * 0.01). assign_to(w); std::set<double> tmp2; zip(my::make_magic_iter(v), my::make_magic_iter(w)). transform_tuple<double>(_1 * _2). insert_into(tmp2). // uniq for_each(std::cout << _1 << "\n"); std::cout << "--- elements of v*w, using operator\n"; (my::make_magic_iter(v) * my::make_magic_iter(w)). for_each(std::cout << _1 << "\n"); } /////////////////////////////////////////////// // magic_iter.h /////////////////////////////////////////////// #ifndef MAGIC_ITER_H #define MAGIC_ITER_H #include <iterator> #include <algorithm> #include <boost/range/iterator_range.hpp> #include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/filter_iterator.hpp> #include <boost/iterator/zip_iterator.hpp> #include <boost/iterator/counting_iterator.hpp> #include <boost/tuple/tuple.hpp> #include <boost/lambda/lambda.hpp> namespace my { // result_type_wrapper is from mailing list post by Maxim Yegorushkin template <class R, class F> struct result_type_wrapper : F { typedef R result_type; explicit result_type_wrapper(const F &f) : F(f) {} }; template <class R, class F> static inline result_type_wrapper<R, F> result_type(const F &f) { return result_type_wrapper<R, F>(f); } template <class R, class F> struct tuple_lambda_wrapper { typedef R result_type; explicit tuple_lambda_wrapper(const F &_f) : f(_f) { } template <class T> R operator()(const T &tuple_val) const { return f( boost::tuples::get<0>(tuple_val), boost::tuples::get<1>(tuple_val) ); } F f; }; template <class R, class F> static inline tuple_lambda_wrapper<R, F> tuple_lambda(const F &f) { return tuple_lambda_wrapper<R, F>(f); } template <class T> class magic_iter : public boost::iterator_range<T> { public: typedef typename std::iterator_traits<T>::value_type value_type; magic_iter(const T &_begin, const T &_end) : boost::iterator_range<T>(_begin, _end) { } template <class F> magic_iter<boost::transform_iterator<F, T> > transform(const F &f) { return magic_iter<boost::transform_iterator<F, T> >( boost::make_transform_iterator(this->begin(), f), boost::make_transform_iterator(this->end(), f) ); } template <class R, class F> magic_iter<boost::transform_iterator< result_type_wrapper<R, F>, T> > transform(const F &f) { return transform(result_type<R>(f)); } template <class R, class F> magic_iter<boost::transform_iterator< tuple_lambda_wrapper<R, F>, T> > transform_tuple(const F &f) { return transform(tuple_lambda<R>(f)); } template <class C> magic_iter<typename C::iterator> assign_to(C &container) { container.assign(this->begin(), this->end()); return make_magic_iter(container); } template <class C> magic_iter<typename C::iterator> insert_into(C &container) { container.insert(this->begin(), this->end()); return make_magic_iter(container); } template <class F> magic_iter<T> &sort(const F &comparator) { std::sort(this->begin(), this->end(), comparator); return *this; } template <class F> magic_iter<boost::filter_iterator<F, T> > filter(const F &f) { return magic_iter<boost::filter_iterator<F, T> >( boost::make_filter_iterator(f, this->begin(), this-
end()), boost::make_filter_iterator(f, this->end(), this->end()) ); }
template <class F> void for_each(const F &f) { std::for_each(this->begin(), this->end(), f); } }; template <class T> magic_iter<typename T::iterator> make_magic_iter(T &container) { return magic_iter<typename T::iterator>(container.begin(), container.end()); } template <class T> magic_iter<typename T::iterator> make_magic_iter(const T &begin, const T &end) { return magic_iter<typename T::iterator>(begin, end); } template <class T> magic_iter<typename boost::counting_iterator<T> > make_magic_counter(const T &begin, const T &end) { return magic_iter<typename boost::counting_iterator<T> >( boost::counting_iterator<T>(begin), boost::counting_iterator<T>(end) ); } template <class A, class B> magic_iter<boost::zip_iterator<boost::tuple<A, B> > > zip(const magic_iter<A> &a, const magic_iter<B> &b) { //return make_magic_iter( return magic_iter<boost::zip_iterator<boost::tuple<A, B> > >( boost::make_zip_iterator( boost::tuple<A, B>(a.begin(), b.begin()) ), boost::make_zip_iterator( boost::tuple<A, B>(a.end(), b.end()) ) ); } template <class X, class Y> struct tuple_multiply { typedef typename boost::lambda::return_type_2< boost::lambda::arithmetic_action< boost::lambda::multiply_action >, X, Y>::type result_type; result_type operator()(const boost::tuple<X, Y> &t) const { const X &x = boost::tuples::get<0>(t); const Y &y = boost::tuples::get<1>(t); return x*y; } }; template <class X, class Y> magic_iter<boost::transform_iterator< tuple_multiply<typename X::value_type, typename Y::value_type>, boost::zip_iterator<boost::tuple<X, Y> >
operator*(magic_iter<X> x, magic_iter<Y> y) { //magic_iter<boost::zip_iterator<boost::tuple<X, Y> > > zi = zip(x, y); //return zi.transform(tuple_multiply<typename X::value_type, typename Y::value_type>()); tuple_multiply<typename X::value_type, typename Y::value_type> op; return zip(x, y).transform(op); }
template <class X, class Y> struct tuple_plus { typedef typename boost::lambda::return_type_2< boost::lambda::arithmetic_action< boost::lambda::plus_action >, X, Y>::type result_type; result_type operator()(const boost::tuple<X, Y> &t) const { const X &x = boost::tuples::get<0>(t); const Y &y = boost::tuples::get<1>(t); return x+y; } }; template <class X, class Y> magic_iter<boost::transform_iterator< tuple_plus<typename X::value_type, typename Y::value_type>, boost::zip_iterator<boost::tuple<X, Y> >
operator+(magic_iter<X> x, magic_iter<Y> y) { tuple_plus<typename X::value_type, typename Y::value_type> op; return zip(x, y).transform(op); }
} // namespace my #endif // MAGIC_ITER_H

I've worked up a subclass that adds Boost.Iterator functionality to a
Boost.Range object.
RangeEx already does that. It was accepted quite some time ago, I'm wondering what its status is.
I am finishing the documentation rework for Quickbook, and doing the modifications requested during the review. A version will be in the sandbox in the next few months. It most certainly is in progress, but has taken longer than I would have liked, of course. Regards, Neil Groves
participants (3)
-
dstahlke
-
Mathias Gaunard
-
Neil Groves