#ifndef SRK31_TRANSFORM_ITERATOR_HPP_ #define SRK31_TRANSFORM_ITERATOR_HPP_ #include #include #include #include /* Most of the time, you should use boost::transform_iterator instead. * But this is factored as a a mixin, so that you can make iterators * which inherit from whatever the base iterator type is. * * See notes in selective_iterator.hpp. */ namespace srk31 { template class transform_iterator; template class transform_iterator_mixin { typedef transform_iterator_mixin self; typedef MixerIn super; public: Func m_func; const Iter& iter() const { return *static_cast(this); } Iter& iter() { return *static_cast< MixerIn *>(this); } // fully specifying constructor transform_iterator_mixin(Iter&& i, const Func& func = Func()) : m_func(func) {} // fully specifying constructor transform_iterator_mixin(const Iter& i, const Func& func = Func()) : m_func(func) {} // default constructor transform_iterator_mixin() {} // copy constructor transform_iterator_mixin(const self& arg) : m_func(arg.m_func) {} // move constructor transform_iterator_mixin(self&& arg) : m_func(std::move(arg.m_func)) {} // assignment self& operator=(const self& arg) { this->m_func = arg.m_func; return *this; } self& operator=(self&& arg) // move assignment { this->m_func = std::move(arg.m_func); return *this; } typedef typename Func::result_type reference; typedef typename std::remove_reference::type value_type; typedef value_type *pointer; typedef typename Iter::difference_type difference_type; typedef typename Iter::iterator_category iterator_category; private: void print_m_func() const { // typedef typename // std::tuple_element<0, typename function_traits::argument_types>::type // first_argument_type; // std::cerr << "Derefing via function (with target? " // << std::boolalpha << m_func.operator bool() // << ") " // << (void*) m_func.template target() // << std::endl; } public: reference operator*() const { this->print_m_func(); return m_func(*iter()); } pointer operator->() const { this->print_m_func(); return &(m_func(*iter())); } self& operator++() // prefix { ++iter(); return *this; } self operator++(int) // postfix ++, so copying { Iter tmp = iter(); ++tmp; return self(std::move(tmp), m_func); } self& operator--() // prefix -- { --iter(); return *this; } self operator--(int) // postfix, so copying { Iter tmp = iter(); --tmp; return self(std::move(tmp), m_func); } bool operator==(const self& arg) const { return iter() == arg.iter(); } bool operator!=(const self& arg) const { return iter() != arg.iter(); } }; template class transform_iterator : public Iter , public transform_iterator_mixin > { typedef transform_iterator self; typedef transform_iterator_mixin super; public: /* We don't just forward the mixin's constructors, because * sometimes Iter will not have a default constructor -- rather, * we have to pass our arguments to both bases. The mixin ignores * any iterator argument, so it's up to Iter to initialize itself * using this. FIXME: probably want to make selective_iterator * consistent with this. */ transform_iterator(Iter&& i, const Func& func = Func()) : Iter(std::move(i)), super(i, func) {} // fully specifying constructor transform_iterator(const Iter& i, const Func& func = Func()) : Iter(i), super(i, func) {} /* In cases where we can default-construct m_func, * we can offer the Iter's constuctors too. */ using Iter::Iter; typedef typename Func::result_type reference; typedef typename std::remove_reference::type value_type; typedef value_type *pointer; typedef typename Iter::difference_type difference_type; typedef typename Iter::iterator_category iterator_category; using super::operator++; using super::operator--; using super::operator!=; using super::operator==; using super::operator*; using super::operator->; }; } // end namespace srk31 #endif