In addition to what has already been suggested, you can do this in much the same way as your sample code.
Example:
template< class IterT, class ObjT, class MemberT > class slicing_iterator; template< class IterT, class ObjT, class MemberT > inline bool operator==( const slicing_iterator<IterT,ObjT,MemberT>& a, const slicing_iterator<IterT,ObjT,MemberT>& b ); template< class IterT, class ObjT, class MemberT > inline bool operator!=( const slicing_iterator<IterT,ObjT,MemberT>& a, const slicing_iterator<IterT,ObjT,MemberT>& b ); template< class IterT, class ObjT, class MemberT > class slicing_iterator { IterT m_iter; MemberT ObjT::* m_member; public: slicing_iterator( IterT iter, MemberT ObjT::*member ) : m_iter(iter), m_member(member) { } slicing_iterator& operator++() { ++m_iter; return *this; } slicing_iterator& operator--() { --m_iter; return *this; } MemberT& operator*() { return static_cast<ObjT&>(*m_iter).*m_member; } const MemberT& operator*() const { return static_cast<const ObjT&>(*m_iter).*m_member; } MemberT* operator->() { return &m_iter->*m_member; } const MemberT* operator->() const { return &m_iter->*m_member; } private: friend bool operator== <IterT,ObjT,MemberT>( const slicing_iterator<IterT,ObjT,MemberT>& a, const slicing_iterator<IterT,ObjT,MemberT>& b ); friend bool operator!= <IterT,ObjT,MemberT>( const slicing_iterator<IterT,ObjT,MemberT>& a, const slicing_iterator<IterT,ObjT,MemberT>& b ); }; template< class IterT, class ObjT, class MemberT > inline bool operator==( const slicing_iterator<IterT,ObjT,MemberT>& a, const slicing_iterator<IterT,ObjT,MemberT>& b ) { return a.m_iter == b.m_iter && a.m_member == a.m_member; } template< class IterT, class ObjT, class MemberT > inline bool operator!=( const slicing_iterator<IterT,ObjT,MemberT>& a, const slicing_iterator<IterT,ObjT,MemberT>& b ) { return a.m_iter != b.m_iter || a.m_member != a.m_member; } template< class IterT, class ObjT, class MemberT > inline slicing_iterator<IterT,ObjT,MemberT> make_slicing_iterator( IterT iter, MemberT ObjT::*member ) { return slicing_iterator<IterT,ObjT,MemberT>( iter, member ); } struct S { int i; char *s; float f; }; int main(void) { std::vector<S> v(10); std::min_element( make_slicing_iterator(v.begin(), &S::f), make_slicing_iterator(v.end(), &S::f) ); return 0; }
At first I didn’t notice - it looks like what @Stuart Golodetz suggested, but the advantage is that the <operator does not need to be defined for the type of iterator (for example, std :: list :: iterator). This makes the implementation universal.