369 lines
10 KiB
Plaintext
369 lines
10 KiB
Plaintext
// Copyright David Abrahams and Thomas Becker 2000-2006.
|
|
// Copyright Kohei Takahashi 2012-2014.
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See
|
|
// accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
|
|
# define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
|
|
|
|
#include <stddef.h>
|
|
#include <boost/iterator.hpp>
|
|
#include <boost/iterator/iterator_traits.hpp>
|
|
#include <boost/iterator/iterator_facade.hpp>
|
|
#include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
|
|
#include <boost/iterator/iterator_categories.hpp>
|
|
|
|
#include <boost/iterator/minimum_category.hpp>
|
|
|
|
#include <utility> // for std::pair
|
|
#include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
|
|
|
|
#include <boost/type_traits/remove_reference.hpp>
|
|
#include <boost/type_traits/remove_cv.hpp>
|
|
|
|
#include <boost/mpl/at.hpp>
|
|
#include <boost/mpl/fold.hpp>
|
|
#include <boost/mpl/transform.hpp>
|
|
#include <boost/mpl/placeholders.hpp>
|
|
|
|
#include <boost/fusion/algorithm/iteration/for_each.hpp>
|
|
#include <boost/fusion/algorithm/transformation/transform.hpp>
|
|
#include <boost/fusion/sequence/convert.hpp>
|
|
#include <boost/fusion/sequence/intrinsic/at_c.hpp>
|
|
#include <boost/fusion/sequence/comparison/equal_to.hpp>
|
|
#include <boost/fusion/support/tag_of_fwd.hpp>
|
|
|
|
namespace boost {
|
|
namespace iterators {
|
|
|
|
// Zip iterator forward declaration for zip_iterator_base
|
|
template<typename IteratorTuple>
|
|
class zip_iterator;
|
|
|
|
namespace detail
|
|
{
|
|
|
|
// Functors to be used with tuple algorithms
|
|
//
|
|
template<typename DiffType>
|
|
class advance_iterator
|
|
{
|
|
public:
|
|
advance_iterator(DiffType step) : m_step(step) {}
|
|
|
|
template<typename Iterator>
|
|
void operator()(Iterator& it) const
|
|
{ it += m_step; }
|
|
|
|
private:
|
|
DiffType m_step;
|
|
};
|
|
//
|
|
struct increment_iterator
|
|
{
|
|
template<typename Iterator>
|
|
void operator()(Iterator& it) const
|
|
{ ++it; }
|
|
};
|
|
//
|
|
struct decrement_iterator
|
|
{
|
|
template<typename Iterator>
|
|
void operator()(Iterator& it) const
|
|
{ --it; }
|
|
};
|
|
//
|
|
struct dereference_iterator
|
|
{
|
|
template<typename>
|
|
struct result;
|
|
|
|
template<typename This, typename Iterator>
|
|
struct result<This(Iterator)>
|
|
{
|
|
typedef typename
|
|
remove_reference<typename remove_cv<Iterator>::type>::type
|
|
iterator;
|
|
|
|
typedef typename iterator_reference<iterator>::type type;
|
|
};
|
|
|
|
template<typename Iterator>
|
|
typename result<dereference_iterator(Iterator)>::type
|
|
operator()(Iterator const& it) const
|
|
{ return *it; }
|
|
};
|
|
|
|
// Metafunction to obtain the type of the tuple whose element types
|
|
// are the reference types of an iterator tuple.
|
|
//
|
|
template<typename IteratorTuple>
|
|
struct tuple_of_references
|
|
: mpl::transform<
|
|
IteratorTuple,
|
|
iterator_reference<mpl::_1>
|
|
>
|
|
{
|
|
};
|
|
|
|
// Specialization for std::pair
|
|
template<typename Iterator1, typename Iterator2>
|
|
struct tuple_of_references<std::pair<Iterator1, Iterator2> >
|
|
{
|
|
typedef std::pair<
|
|
typename iterator_reference<Iterator1>::type
|
|
, typename iterator_reference<Iterator2>::type
|
|
> type;
|
|
};
|
|
|
|
// Metafunction to obtain the minimal traversal tag in a tuple
|
|
// of iterators.
|
|
//
|
|
template<typename IteratorTuple>
|
|
struct minimum_traversal_category_in_iterator_tuple
|
|
{
|
|
typedef typename mpl::transform<
|
|
IteratorTuple
|
|
, pure_traversal_tag<iterator_traversal<> >
|
|
>::type tuple_of_traversal_tags;
|
|
|
|
typedef typename mpl::fold<
|
|
tuple_of_traversal_tags
|
|
, random_access_traversal_tag
|
|
, minimum_category<>
|
|
>::type type;
|
|
};
|
|
|
|
template<typename Iterator1, typename Iterator2>
|
|
struct minimum_traversal_category_in_iterator_tuple<std::pair<Iterator1, Iterator2> >
|
|
{
|
|
typedef typename pure_traversal_tag<
|
|
typename iterator_traversal<Iterator1>::type
|
|
>::type iterator1_traversal;
|
|
typedef typename pure_traversal_tag<
|
|
typename iterator_traversal<Iterator2>::type
|
|
>::type iterator2_traversal;
|
|
|
|
typedef typename minimum_category<
|
|
iterator1_traversal
|
|
, typename minimum_category<
|
|
iterator2_traversal
|
|
, random_access_traversal_tag
|
|
>::type
|
|
>::type type;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Class zip_iterator_base
|
|
//
|
|
// Builds and exposes the iterator facade type from which the zip
|
|
// iterator will be derived.
|
|
//
|
|
template<typename IteratorTuple>
|
|
struct zip_iterator_base
|
|
{
|
|
private:
|
|
// Reference type is the type of the tuple obtained from the
|
|
// iterators' reference types.
|
|
typedef typename
|
|
detail::tuple_of_references<IteratorTuple>::type reference;
|
|
|
|
// Value type is the same as reference type.
|
|
typedef reference value_type;
|
|
|
|
// Difference type is the first iterator's difference type
|
|
typedef typename iterator_difference<
|
|
typename mpl::at_c<IteratorTuple, 0>::type
|
|
>::type difference_type;
|
|
|
|
// Traversal catetgory is the minimum traversal category in the
|
|
// iterator tuple.
|
|
typedef typename
|
|
detail::minimum_traversal_category_in_iterator_tuple<
|
|
IteratorTuple
|
|
>::type traversal_category;
|
|
public:
|
|
|
|
// The iterator facade type from which the zip iterator will
|
|
// be derived.
|
|
typedef iterator_facade<
|
|
zip_iterator<IteratorTuple>,
|
|
value_type,
|
|
traversal_category,
|
|
reference,
|
|
difference_type
|
|
> type;
|
|
};
|
|
|
|
template <>
|
|
struct zip_iterator_base<int>
|
|
{
|
|
typedef int type;
|
|
};
|
|
|
|
template <typename reference>
|
|
struct converter
|
|
{
|
|
template <typename Seq>
|
|
static reference call(Seq seq)
|
|
{
|
|
typedef typename fusion::traits::tag_of<reference>::type tag;
|
|
return fusion::convert<tag>(seq);
|
|
}
|
|
};
|
|
|
|
template <typename Reference1, typename Reference2>
|
|
struct converter<std::pair<Reference1, Reference2> >
|
|
{
|
|
typedef std::pair<Reference1, Reference2> reference;
|
|
template <typename Seq>
|
|
static reference call(Seq seq)
|
|
{
|
|
return reference(
|
|
fusion::at_c<0>(seq)
|
|
, fusion::at_c<1>(seq));
|
|
}
|
|
};
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// zip_iterator class definition
|
|
//
|
|
template<typename IteratorTuple>
|
|
class zip_iterator :
|
|
public detail::zip_iterator_base<IteratorTuple>::type
|
|
{
|
|
|
|
// Typedef super_t as our base class.
|
|
typedef typename
|
|
detail::zip_iterator_base<IteratorTuple>::type super_t;
|
|
|
|
// iterator_core_access is the iterator's best friend.
|
|
friend class iterator_core_access;
|
|
|
|
public:
|
|
|
|
// Construction
|
|
// ============
|
|
|
|
// Default constructor
|
|
zip_iterator() { }
|
|
|
|
// Constructor from iterator tuple
|
|
zip_iterator(IteratorTuple iterator_tuple)
|
|
: m_iterator_tuple(iterator_tuple)
|
|
{ }
|
|
|
|
// Copy constructor
|
|
template<typename OtherIteratorTuple>
|
|
zip_iterator(
|
|
const zip_iterator<OtherIteratorTuple>& other,
|
|
typename enable_if_convertible<
|
|
OtherIteratorTuple,
|
|
IteratorTuple
|
|
>::type* = 0
|
|
) : m_iterator_tuple(other.get_iterator_tuple())
|
|
{}
|
|
|
|
// Get method for the iterator tuple.
|
|
const IteratorTuple& get_iterator_tuple() const
|
|
{ return m_iterator_tuple; }
|
|
|
|
private:
|
|
|
|
// Implementation of Iterator Operations
|
|
// =====================================
|
|
|
|
// Dereferencing returns a tuple built from the dereferenced
|
|
// iterators in the iterator tuple.
|
|
typename super_t::reference dereference() const
|
|
{
|
|
typedef typename super_t::reference reference;
|
|
typedef detail::converter<reference> gen;
|
|
return gen::call(fusion::transform(
|
|
get_iterator_tuple(),
|
|
detail::dereference_iterator()));
|
|
}
|
|
|
|
// Two zip iterators are equal if all iterators in the iterator
|
|
// tuple are equal. NOTE: It should be possible to implement this
|
|
// as
|
|
//
|
|
// return get_iterator_tuple() == other.get_iterator_tuple();
|
|
//
|
|
// but equality of tuples currently (7/2003) does not compile
|
|
// under several compilers. No point in bringing in a bunch
|
|
// of #ifdefs here.
|
|
//
|
|
template<typename OtherIteratorTuple>
|
|
bool equal(const zip_iterator<OtherIteratorTuple>& other) const
|
|
{
|
|
return fusion::equal_to(
|
|
get_iterator_tuple(),
|
|
other.get_iterator_tuple());
|
|
}
|
|
|
|
// Advancing a zip iterator means to advance all iterators in the
|
|
// iterator tuple.
|
|
void advance(typename super_t::difference_type n)
|
|
{
|
|
fusion::for_each(
|
|
m_iterator_tuple,
|
|
detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n));
|
|
}
|
|
// Incrementing a zip iterator means to increment all iterators in
|
|
// the iterator tuple.
|
|
void increment()
|
|
{
|
|
fusion::for_each(
|
|
m_iterator_tuple,
|
|
detail::increment_iterator());
|
|
}
|
|
|
|
// Decrementing a zip iterator means to decrement all iterators in
|
|
// the iterator tuple.
|
|
void decrement()
|
|
{
|
|
fusion::for_each(
|
|
m_iterator_tuple,
|
|
detail::decrement_iterator());
|
|
}
|
|
|
|
// Distance is calculated using the first iterator in the tuple.
|
|
template<typename OtherIteratorTuple>
|
|
typename super_t::difference_type distance_to(
|
|
const zip_iterator<OtherIteratorTuple>& other
|
|
) const
|
|
{
|
|
return fusion::at_c<0>(other.get_iterator_tuple()) -
|
|
fusion::at_c<0>(this->get_iterator_tuple());
|
|
}
|
|
|
|
// Data Members
|
|
// ============
|
|
|
|
// The iterator tuple.
|
|
IteratorTuple m_iterator_tuple;
|
|
|
|
};
|
|
|
|
// Make function for zip iterator
|
|
//
|
|
template<typename IteratorTuple>
|
|
inline zip_iterator<IteratorTuple>
|
|
make_zip_iterator(IteratorTuple t)
|
|
{ return zip_iterator<IteratorTuple>(t); }
|
|
|
|
} // namespace iterators
|
|
|
|
using iterators::zip_iterator;
|
|
using iterators::make_zip_iterator;
|
|
|
|
} // namespace boost
|
|
|
|
#endif
|