#ifndef ITERATORS_TUPLEIT_HH #define ITERATORS_TUPLEIT_HH #include #include #include #include #include #include "boost/tuple/tuple.hpp" #include "boost/tuple/tuple_comparison.hpp" #include "boost/utility.hpp" #include "boost/type_traits.hpp" #include "boost/optional.hpp" // for aligned_storage #include namespace iterators { namespace detail { void preincrementTuple(boost::tuples::null_type) { } template void preincrementTuple(TupleType& lhs) { preincrementTuple(lhs.get_tail()); ++(lhs.template get<0>()); } void predecrementTuple(boost::tuples::null_type) { } template void predecrementTuple(TupleType& lhs) { predecrementTuple(lhs.get_tail()); --(lhs.template get<0>()); } template void addToTuple(boost::tuples::null_type,difference_type) { } template void addToTuple(TupleType& lhs,difference_type diff) { addToTuple(lhs.get_tail(),diff); lhs.template get<0>()+=diff; } template void subFromTuple(boost::tuples::null_type,difference_type) { } template void subFromTuple(TupleType& lhs,difference_type diff) { subFromTuple(lhs.get_tail(),diff); lhs.template get<0>()-=diff; } template difference_type diffTuples(TupleType const& lhs,TupleType const& rhs); template struct DiffTupleHelper { static difference_type doDiff(TupleType const& lhs,TupleType const& rhs) { difference_type res1=lhs.template get<0>()-rhs.template get<0>(); difference_type res2=diffTuples(lhs.get_tail(),rhs.get_tail()); if(res1==res2) { return res1; } throw std::logic_error("The iterators in the tuples are mismatched"); } }; template struct DiffTupleHelper > { static difference_type doDiff(boost::tuples::cons const& lhs,boost::tuples::cons const& rhs) { return lhs.template get<0>()-rhs.template get<0>(); } }; template difference_type diffTuples(TupleType const& lhs,TupleType const& rhs) { return DiffTupleHelper::doDiff(lhs,rhs); } template struct MakeTupleTypeWithReferences { typedef MakeTupleTypeWithReferences TailTupleTypeBuilder; typedef typename TailTupleTypeBuilder::Type TailTupleType; typedef boost::tuples::cons::type, TailTupleType> Type; template static Type makeTuple(Tuple& source) { return Type(source.get_head(),TailTupleTypeBuilder::makeTuple(source.get_tail())); } }; template<> struct MakeTupleTypeWithReferences { typedef boost::tuples::null_type Type; static Type makeTuple(boost::tuples::null_type) { return Type(); } }; typedef char Tiny; struct Small { Tiny dummy[2]; }; struct Medium { Small dummy[2]; }; struct Large { Medium dummy[2]; }; struct Huge { Large dummy[2]; }; template struct CategoryMap { typedef void Type; }; // Tiny categoryCheck(std::output_iterator_tag*); Small categoryCheck(std::input_iterator_tag*); Medium categoryCheck(std::forward_iterator_tag*); Large categoryCheck(std::bidirectional_iterator_tag*); Huge categoryCheck(std::random_access_iterator_tag*); // template<> // struct CategoryMap // { // typedef std::output_iterator_tag Type; // }; template<> struct CategoryMap { typedef std::input_iterator_tag Type; }; template<> struct CategoryMap { typedef std::forward_iterator_tag Type; }; template<> struct CategoryMap { typedef std::bidirectional_iterator_tag Type; }; template<> struct CategoryMap { typedef std::random_access_iterator_tag Type; }; template struct CommonCategory { private: enum {categorySize=sizeof(::iterators::detail::categoryCheck(false?(Cat1*)0:(Cat2*)0)) }; public: typedef typename CategoryMap::Type Type; }; // specializations template struct CommonCategory { typedef std::output_iterator_tag Type; }; template struct CommonCategory { typedef std::output_iterator_tag Type; }; template<> struct CommonCategory { typedef std::output_iterator_tag Type; }; template<> struct CommonCategory { // no Type, because error }; template<> struct CommonCategory { // no Type, because error }; void derefAndWrite(boost::tuples::null_type,boost::tuples::null_type) {} template void derefAndWrite(IterTuple& iters,SourceTuple const& source) { *iters.get_head()=source.get_head(); derefAndWrite(iters.get_tail(),source.get_tail()); } } // An OutputTuple holds a tuple of references to iterators, and writes to them on assignment template struct OutputTuple: public detail::MakeTupleTypeWithReferences::Type, boost::noncopyable { private: typedef detail::MakeTupleTypeWithReferences BaseTypeBuilder; typedef typename BaseTypeBuilder::Type BaseType; public: OutputTuple(IterTuple& iters): BaseType(BaseTypeBuilder::makeTuple(iters)) {} template OutputTuple& operator=(const SomeTuple& other) { detail::derefAndWrite(static_cast(*this),other); return *this; } }; // An OwningRefTuple holds a tuple of references, // which may point to data within the tuple, or external to it namespace detail { struct PreserveReferences {}; template struct OwningBase { std::auto_ptr tupleBuf; OwningBase() {} template OwningBase(SomeType &source): tupleBuf(new OwnedType(source)) {} }; } template struct OwningRefTuple: private detail::OwningBase, public detail::MakeTupleTypeWithReferences::Type { private: typedef detail::MakeTupleTypeWithReferences BaseTypeBuilder; typedef typename BaseTypeBuilder::Type BaseType; typedef detail::OwningBase OwningBaseType; public: typedef typename BaseType::head_type head_type; typedef typename BaseType::tail_type tail_type; private: typedef TupleType OwnedTuple; OwnedTuple* getTuplePtr() { return this->tupleBuf.get(); } public: // copy from other types of tuples too template OwningRefTuple(const SomeTuple& other): OwningBaseType(other),BaseType(BaseTypeBuilder::makeTuple(*getTuplePtr())) { } // copying copies values by default OwningRefTuple(const OwningRefTuple& other): OwningBaseType(other),BaseType(BaseTypeBuilder::makeTuple(*getTuplePtr())) { } // allow user to specify // whether to preserve references template OwningRefTuple(SomeTuple& other,detail::PreserveReferences const&): BaseType(BaseTypeBuilder::makeTuple(other)) { } // assignment assigns to referenced values template OwningRefTuple& operator=(const SomeTuple& other) { BaseType::operator=(other); return *this; } OwningRefTuple& operator=(const OwningRefTuple& other) { BaseType::operator=(other); return *this; } }; namespace detail { template struct DerefIterTupleHelperKeepRef { typedef boost::tuples::cons::value_type>::type, typename DerefIterTupleHelperKeepRef::Type> Type; }; template<> struct DerefIterTupleHelperKeepRef { typedef boost::tuples::null_type Type; }; template<> struct DerefIterTupleHelperKeepRef { typedef boost::tuples::null_type Type; }; template struct DerefIterTupleHelperNoRef { typedef boost::tuples::cons::value_type, typename DerefIterTupleHelperNoRef::Type> Type; }; template<> struct DerefIterTupleHelperNoRef { typedef boost::tuples::null_type Type; }; template<> struct DerefIterTupleHelperNoRef { typedef boost::tuples::null_type Type; }; boost::tuples::null_type derefIterTupleKeepRef(boost::tuples::null_type const& iters) { return iters; } template const typename DerefIterTupleHelperKeepRef::Type derefIterTupleKeepRef(IterTuple& iters) { return typename DerefIterTupleHelperKeepRef::Type(*iters.template get<0>(),derefIterTupleKeepRef(iters.get_tail())); } boost::tuples::null_type derefIterTupleNoRef(boost::tuples::null_type const& iters) { return iters; } template typename DerefIterTupleHelperNoRef::Type derefIterTupleNoRef(IterTuple& iters) { return typename DerefIterTupleHelperNoRef::Type(*iters.template get<0>(),derefIterTupleNoRef(iters.get_tail())); } // Define, construct and destroy the appropriate value_type for // the given iterator category template struct ValueForCategory { private: typedef typename IterTuple::head_type HeadIterType; typedef typename IterTuple::tail_type TailTupleType; typedef typename std::iterator_traits::value_type HeadValueType; typedef typename ValueForCategory::ValueTuple TailValueTuple; public: typedef boost::tuples::cons ValueTuple; typedef OwningRefTuple value_type; typedef value_type Type; static void construct(Type* p,IterTuple const& iters) { // don't copy values, keep as references new (p) Type(derefIterTupleKeepRef(iters),::iterators::detail::PreserveReferences()); } static void destruct(Type* p) { p->~OwningRefTuple(); } }; template struct ValueForCategory { private: public: typedef boost::tuples::null_type ValueTuple; }; template struct ValueForCategory { private: typedef typename IterTuple::head_type HeadIterType; typedef typename IterTuple::tail_type TailTupleType; typedef typename std::iterator_traits::value_type HeadValueType; typedef typename ValueForCategory::ValueTuple TailValueTuple; public: typedef boost::tuples::cons ValueTuple; typedef OwningRefTuple value_type; typedef value_type Type; static void construct(Type* p,IterTuple const& iters) { // copy values new (p) Type(derefIterTupleNoRef(iters)); } static void destruct(Type* p) { p->~OwningRefTuple(); } }; template<> struct ValueForCategory { private: public: typedef boost::tuples::null_type ValueTuple; }; template struct ValueForCategory { public: typedef OutputTuple value_type; typedef value_type Type; static void construct(Type* p,IterTuple& iters) { // copy values new (p) Type(iters); } static void destruct(Type* p) { p->~OutputTuple(); } }; template<> struct ValueForCategory { private: public: }; template struct VFCSelector { typedef ValueForCategory Type; }; // Select the iterator_category and value_type for our TupleIt template struct TupleItHelper { typedef typename IterTuple::head_type HeadIterType; typedef typename IterTuple::tail_type TailTupleType; typedef typename std::iterator_traits::iterator_category Cat1; typedef typename TupleItHelper::iterator_category Cat2; typedef typename CommonCategory::Type iterator_category; typedef typename VFCSelector::Type ValueTypeDef; typedef typename ValueTypeDef::value_type value_type; typedef typename ValueTypeDef::Type DeRefType; typedef DeRefType& reference; typedef DeRefType* pointer; typedef std::ptrdiff_t difference_type; typedef std::iterator IteratorType; static void construct(DeRefType* p,IterTuple& iters) { ValueTypeDef::construct(p,iters); } static void destruct(DeRefType* p) { ValueTypeDef::destruct(p); } }; template<> struct TupleItHelper { typedef std::random_access_iterator_tag iterator_category; }; } // the actual Tuple Iterator itself template struct TupleIt: public detail::TupleItHelper::IteratorType { private: typedef detail::TupleItHelper TupleDefs; public: typedef typename TupleDefs::iterator_category iterator_category; typedef typename TupleDefs::value_type value_type; typedef typename TupleDefs::difference_type difference_type; typedef typename TupleDefs::reference reference; typedef typename TupleDefs::pointer pointer; private: pointer getValuePtr() const { return reinterpret_cast(dataCache.address()); } void emptyCache() const { if(cacheInitialized) { TupleDefs::destruct(getValuePtr()); cacheInitialized=false; } } void initCache() const { emptyCache(); TupleDefs::construct(getValuePtr(),iters); cacheInitialized=true; } public: TupleIt(IterTuple iters_): iters(iters_),cacheInitialized(false) {} template TupleIt(const TupleIt& other): iters(other.iters),cacheInitialized(false) {} TupleIt(const TupleIt& other): iters(other.iters),cacheInitialized(false) {} TupleIt(): iters(),cacheInitialized(false) {} ~TupleIt() { emptyCache(); } void swap(TupleIt& other) { using std::swap; swap(iters,other.iters); } TupleIt& operator=(TupleIt const& other) { emptyCache(); iters=other.iters; return *this; } // Input Iterator requirements reference operator*() const { initCache(); return *getValuePtr(); } pointer operator->() const { initCache(); return getValuePtr(); } friend bool operator==(const TupleIt& lhs,const TupleIt& rhs) { return lhs.iters==rhs.iters; } friend bool operator!=(const TupleIt& lhs,const TupleIt& rhs) { return lhs.iters!=rhs.iters; } // Forward Iterator requirements TupleIt& operator++() { detail::preincrementTuple(iters); return *this; } TupleIt operator++(int) { TupleIt temp(*this); ++*this; return temp; } // Bidirectional Iterator requirements TupleIt& operator--() { detail::predecrementTuple(iters); return *this; } TupleIt operator--(int) { TupleIt temp(*this); --*this; return temp; } // Random-Access Iterator requirements TupleIt& operator+=(difference_type n) { detail::addToTuple(iters,n); return *this; } TupleIt& operator-=(difference_type n) { detail::subFromTuple(iters,n); return *this; } friend difference_type operator-(const TupleIt& a,const TupleIt& b) { return detail::diffTuples(a.iters,b.iters); } value_type operator[](difference_type n) const { return *(*this+n); } private: // everything is mutable so we can modify it without affecting const correctness // of client code mutable IterTuple iters; mutable boost::optional_detail::aligned_storage dataCache; mutable bool cacheInitialized; }; // more random-access iterator requirements template TupleIt operator+(std::ptrdiff_t n,TupleIt temp) { temp+=n; return temp; } template TupleIt operator+(TupleIt temp,std::ptrdiff_t n) { temp+=n; return temp; } template TupleIt operator-(TupleIt temp,std::ptrdiff_t n) { temp-=n; return temp; } template bool operator<(const TupleIt& a,const TupleIt& b) { return (b-a)>0; } template bool operator>(const TupleIt& a,const TupleIt& b) { return b bool operator>=(const TupleIt& a,const TupleIt& b) { return !(b bool operator<=(const TupleIt& a,const TupleIt& b) { return !(b>a); } // implementation of swap and iter_swap template void swap(TupleIt& lhs,TupleIt& rhs) { lhs.swap(rhs); } // template // void iter_swap(const TupleIt& lhs,const TupleIt& rhs) // { // lhs.iter_swap(rhs); // } template TupleIt > makeTupleIterator(Iter1 i1,Iter2 i2) { return TupleIt >(boost::make_tuple(i1,i2)); } template TupleIt > makeTupleIterator(Iter1 i1,Iter2 i2,Iter3 i3) { return TupleIt >(boost::make_tuple(i1,i2,i3)); } template TupleIt > makeTupleIterator(Iter1 i1,Iter2 i2,Iter3 i3,Iter4 i4) { return TupleIt >(boost::make_tuple(i1,i2,i3,i4)); } } #endif