-// Copyright David Abrahams and Thomas Becker 2000-2006. Distributed\r
-// under the Boost Software License, Version 1.0. (See accompanying\r
-// file LICENSE_1_0.txt or copy at\r
-// http://www.boost.org/LICENSE_1_0.txt)\r
-\r
-#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_\r
-# define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_\r
-\r
-#include <stddef.h>\r
-#include <boost/iterator.hpp>\r
-#include <boost/iterator/iterator_traits.hpp>\r
-#include <boost/iterator/iterator_facade.hpp>\r
-#include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible\r
-#include <boost/iterator/iterator_categories.hpp>\r
-#include <boost/detail/iterator.hpp>\r
-\r
-#include <boost/iterator/detail/minimum_category.hpp>\r
-\r
-#include <boost/tuple/tuple.hpp>\r
-\r
-#include <boost/type_traits/is_same.hpp>\r
-#include <boost/mpl/and.hpp>\r
-#include <boost/mpl/apply.hpp>\r
-#include <boost/mpl/eval_if.hpp>\r
-#include <boost/mpl/lambda.hpp>\r
-#include <boost/mpl/placeholders.hpp>\r
-#include <boost/mpl/aux_/lambda_support.hpp>\r
-\r
-namespace boost {\r
-\r
- // Zip iterator forward declaration for zip_iterator_base\r
- template<typename IteratorTuple>\r
- class zip_iterator;\r
-\r
- // One important design goal of the zip_iterator is to isolate all\r
- // functionality whose implementation relies on the current tuple\r
- // implementation. This goal has been achieved as follows: Inside\r
- // the namespace detail there is a namespace tuple_impl_specific.\r
- // This namespace encapsulates all functionality that is specific\r
- // to the current Boost tuple implementation. More precisely, the\r
- // namespace tuple_impl_specific provides the following tuple\r
- // algorithms and meta-algorithms for the current Boost tuple\r
- // implementation:\r
- //\r
- // tuple_meta_transform\r
- // tuple_meta_accumulate\r
- // tuple_transform\r
- // tuple_for_each\r
- //\r
- // If the tuple implementation changes, all that needs to be\r
- // replaced is the implementation of these four (meta-)algorithms.\r
-\r
- namespace detail\r
- {\r
-\r
- // Functors to be used with tuple algorithms\r
- //\r
- template<typename DiffType>\r
- class advance_iterator\r
- {\r
- public:\r
- advance_iterator(DiffType step) : m_step(step) {}\r
- \r
- template<typename Iterator>\r
- void operator()(Iterator& it) const\r
- { it += m_step; }\r
-\r
- private:\r
- DiffType m_step;\r
- };\r
- //\r
- struct increment_iterator\r
- {\r
- template<typename Iterator>\r
- void operator()(Iterator& it)\r
- { ++it; }\r
- };\r
- //\r
- struct decrement_iterator\r
- {\r
- template<typename Iterator>\r
- void operator()(Iterator& it)\r
- { --it; }\r
- };\r
- //\r
- struct dereference_iterator\r
- {\r
- template<typename Iterator>\r
- struct apply\r
- { \r
- typedef typename\r
- iterator_traits<Iterator>::reference\r
- type;\r
- };\r
-\r
- template<typename Iterator>\r
- typename apply<Iterator>::type operator()(Iterator const& it)\r
- { return *it; }\r
- };\r
- \r
-\r
- // The namespace tuple_impl_specific provides two meta-\r
- // algorithms and two algorithms for tuples.\r
- //\r
- namespace tuple_impl_specific\r
- {\r
- // Meta-transform algorithm for tuples\r
- //\r
- template<typename Tuple, class UnaryMetaFun>\r
- struct tuple_meta_transform;\r
- \r
- template<typename Tuple, class UnaryMetaFun>\r
- struct tuple_meta_transform_impl\r
- {\r
- typedef tuples::cons<\r
- typename mpl::apply1<\r
- typename mpl::lambda<UnaryMetaFun>::type\r
- , typename Tuple::head_type\r
- >::type\r
- , typename tuple_meta_transform<\r
- typename Tuple::tail_type\r
- , UnaryMetaFun \r
- >::type\r
- > type;\r
- };\r
-\r
- template<typename Tuple, class UnaryMetaFun>\r
- struct tuple_meta_transform\r
- : mpl::eval_if<\r
- boost::is_same<Tuple, tuples::null_type>\r
- , mpl::identity<tuples::null_type>\r
- , tuple_meta_transform_impl<Tuple, UnaryMetaFun>\r
- >\r
- {\r
- };\r
- \r
- // Meta-accumulate algorithm for tuples. Note: The template \r
- // parameter StartType corresponds to the initial value in \r
- // ordinary accumulation.\r
- //\r
- template<class Tuple, class BinaryMetaFun, class StartType>\r
- struct tuple_meta_accumulate;\r
- \r
- template<\r
- typename Tuple\r
- , class BinaryMetaFun\r
- , typename StartType\r
- >\r
- struct tuple_meta_accumulate_impl\r
- {\r
- typedef typename mpl::apply2<\r
- typename mpl::lambda<BinaryMetaFun>::type\r
- , typename Tuple::head_type\r
- , typename tuple_meta_accumulate<\r
- typename Tuple::tail_type\r
- , BinaryMetaFun\r
- , StartType \r
- >::type\r
- >::type type;\r
- };\r
-\r
- template<\r
- typename Tuple\r
- , class BinaryMetaFun\r
- , typename StartType\r
- >\r
- struct tuple_meta_accumulate\r
- : mpl::eval_if<\r
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)\r
- mpl::or_<\r
-#endif \r
- boost::is_same<Tuple, tuples::null_type>\r
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)\r
- , boost::is_same<Tuple,int>\r
- >\r
-#endif \r
- , mpl::identity<StartType>\r
- , tuple_meta_accumulate_impl<\r
- Tuple\r
- , BinaryMetaFun\r
- , StartType\r
- >\r
- >\r
- {\r
- }; \r
-\r
-#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \\r
- || ( \\r
- BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \\r
- )\r
-// Not sure why intel's partial ordering fails in this case, but I'm\r
-// assuming int's an MSVC bug-compatibility feature.\r
- \r
-# define BOOST_TUPLE_ALGO_DISPATCH\r
-# define BOOST_TUPLE_ALGO(algo) algo##_impl\r
-# define BOOST_TUPLE_ALGO_TERMINATOR , int\r
-# define BOOST_TUPLE_ALGO_RECURSE , ...\r
-#else \r
-# define BOOST_TUPLE_ALGO(algo) algo\r
-# define BOOST_TUPLE_ALGO_TERMINATOR\r
-# define BOOST_TUPLE_ALGO_RECURSE\r
-#endif\r
- \r
- // transform algorithm for tuples. The template parameter Fun\r
- // must be a unary functor which is also a unary metafunction\r
- // class that computes its return type based on its argument\r
- // type. For example:\r
- //\r
- // struct to_ptr\r
- // {\r
- // template <class Arg>\r
- // struct apply\r
- // {\r
- // typedef Arg* type;\r
- // }\r
- //\r
- // template <class Arg>\r
- // Arg* operator()(Arg x);\r
- // };\r
- template<typename Fun>\r
- tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)\r
- (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)\r
- { return tuples::null_type(); }\r
-\r
- template<typename Tuple, typename Fun>\r
- typename tuple_meta_transform<\r
- Tuple\r
- , Fun\r
- >::type\r
- \r
- BOOST_TUPLE_ALGO(tuple_transform)(\r
- const Tuple& t, \r
- Fun f\r
- BOOST_TUPLE_ALGO_RECURSE\r
- )\r
- { \r
- typedef typename tuple_meta_transform<\r
- BOOST_DEDUCED_TYPENAME Tuple::tail_type\r
- , Fun\r
- >::type transformed_tail_type;\r
-\r
- return tuples::cons<\r
- BOOST_DEDUCED_TYPENAME mpl::apply1<\r
- Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type\r
- >::type\r
- , transformed_tail_type\r
- >( \r
- f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)\r
- );\r
- }\r
-\r
-#ifdef BOOST_TUPLE_ALGO_DISPATCH\r
- template<typename Tuple, typename Fun>\r
- typename tuple_meta_transform<\r
- Tuple\r
- , Fun\r
- >::type\r
- \r
- tuple_transform(\r
- const Tuple& t, \r
- Fun f\r
- )\r
- {\r
- return tuple_transform_impl(t, f, 1);\r
- }\r
-#endif\r
- \r
- // for_each algorithm for tuples.\r
- //\r
- template<typename Fun>\r
- Fun BOOST_TUPLE_ALGO(tuple_for_each)(\r
- tuples::null_type\r
- , Fun f BOOST_TUPLE_ALGO_TERMINATOR\r
- )\r
- { return f; }\r
-\r
- \r
- template<typename Tuple, typename Fun>\r
- Fun BOOST_TUPLE_ALGO(tuple_for_each)(\r
- Tuple& t\r
- , Fun f BOOST_TUPLE_ALGO_RECURSE)\r
- { \r
- f( t.get_head() );\r
- return tuple_for_each(t.get_tail(), f);\r
- }\r
- \r
-#ifdef BOOST_TUPLE_ALGO_DISPATCH\r
- template<typename Tuple, typename Fun>\r
- Fun\r
- tuple_for_each(\r
- Tuple& t, \r
- Fun f\r
- )\r
- {\r
- return tuple_for_each_impl(t, f, 1);\r
- }\r
-#endif\r
- \r
- // Equality of tuples. NOTE: "==" for tuples currently (7/2003)\r
- // has problems under some compilers, so I just do my own.\r
- // No point in bringing in a bunch of #ifdefs here. This is\r
- // going to go away with the next tuple implementation anyway.\r
- //\r
- inline bool tuple_equal(tuples::null_type, tuples::null_type)\r
- { return true; }\r
-\r
- template<typename Tuple1, typename Tuple2>\r
- bool tuple_equal(\r
- Tuple1 const& t1, \r
- Tuple2 const& t2\r
- )\r
- { \r
- return t1.get_head() == t2.get_head() && \r
- tuple_equal(t1.get_tail(), t2.get_tail());\r
- }\r
- }\r
- //\r
- // end namespace tuple_impl_specific\r
-\r
- template<typename Iterator>\r
- struct iterator_reference\r
- {\r
- typedef typename iterator_traits<Iterator>::reference type;\r
- };\r
-\r
-#ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT\r
- // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work\r
- // out well. Instantiating the nested apply template also\r
- // requires instantiating iterator_traits on the\r
- // placeholder. Instead we just specialize it as a metafunction\r
- // class.\r
- template<>\r
- struct iterator_reference<mpl::_1>\r
- {\r
- template <class T>\r
- struct apply : iterator_reference<T> {};\r
- };\r
-#endif\r
- \r
- // Metafunction to obtain the type of the tuple whose element types\r
- // are the reference types of an iterator tuple.\r
- //\r
- template<typename IteratorTuple>\r
- struct tuple_of_references\r
- : tuple_impl_specific::tuple_meta_transform<\r
- IteratorTuple, \r
- iterator_reference<mpl::_1>\r
- >\r
- {\r
- };\r
-\r
- // Metafunction to obtain the minimal traversal tag in a tuple\r
- // of iterators.\r
- //\r
- template<typename IteratorTuple>\r
- struct minimum_traversal_category_in_iterator_tuple\r
- {\r
- typedef typename tuple_impl_specific::tuple_meta_transform<\r
- IteratorTuple\r
- , iterator_traversal<>\r
- >::type tuple_of_traversal_tags;\r
- \r
- typedef typename tuple_impl_specific::tuple_meta_accumulate<\r
- tuple_of_traversal_tags\r
- , minimum_category<>\r
- , random_access_traversal_tag\r
- >::type type;\r
- };\r
-\r
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround\r
- template <>\r
- struct minimum_traversal_category_in_iterator_tuple<int>\r
- {\r
- typedef int type;\r
- };\r
-#endif\r
- \r
- // We need to call tuple_meta_accumulate with mpl::and_ as the\r
- // accumulating functor. To this end, we need to wrap it into\r
- // a struct that has exactly two arguments (that is, template\r
- // parameters) and not five, like mpl::and_ does.\r
- //\r
- template<typename Arg1, typename Arg2>\r
- struct and_with_two_args\r
- : mpl::and_<Arg1, Arg2>\r
- {\r
- };\r
- \r
-# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT\r
- // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work\r
- // out well. In this case I think it's an MPL bug\r
- template<>\r
- struct and_with_two_args<mpl::_1,mpl::_2>\r
- {\r
- template <class A1, class A2>\r
- struct apply : mpl::and_<A1,A2>\r
- {};\r
- };\r
-# endif \r
-\r
- ///////////////////////////////////////////////////////////////////\r
- //\r
- // Class zip_iterator_base\r
- //\r
- // Builds and exposes the iterator facade type from which the zip \r
- // iterator will be derived.\r
- //\r
- template<typename IteratorTuple>\r
- struct zip_iterator_base\r
- {\r
- private:\r
- // Reference type is the type of the tuple obtained from the\r
- // iterators' reference types.\r
- typedef typename \r
- detail::tuple_of_references<IteratorTuple>::type reference;\r
- \r
- // Value type is the same as reference type.\r
- typedef reference value_type;\r
- \r
- // Difference type is the first iterator's difference type\r
- typedef typename iterator_traits<\r
- typename tuples::element<0, IteratorTuple>::type\r
- >::difference_type difference_type;\r
- \r
- // Traversal catetgory is the minimum traversal category in the \r
- // iterator tuple.\r
- typedef typename \r
- detail::minimum_traversal_category_in_iterator_tuple<\r
- IteratorTuple\r
- >::type traversal_category;\r
- public:\r
- \r
- // The iterator facade type from which the zip iterator will\r
- // be derived.\r
- typedef iterator_facade<\r
- zip_iterator<IteratorTuple>,\r
- value_type, \r
- traversal_category,\r
- reference,\r
- difference_type\r
- > type;\r
- };\r
-\r
- template <>\r
- struct zip_iterator_base<int>\r
- {\r
- typedef int type;\r
- };\r
- }\r
- \r
- /////////////////////////////////////////////////////////////////////\r
- //\r
- // zip_iterator class definition\r
- //\r
- template<typename IteratorTuple>\r
- class zip_iterator : \r
- public detail::zip_iterator_base<IteratorTuple>::type\r
- { \r
-\r
- // Typedef super_t as our base class. \r
- typedef typename \r
- detail::zip_iterator_base<IteratorTuple>::type super_t;\r
-\r
- // iterator_core_access is the iterator's best friend.\r
- friend class iterator_core_access;\r
-\r
- public:\r
- \r
- // Construction\r
- // ============\r
- \r
- // Default constructor\r
- zip_iterator() { }\r
-\r
- // Constructor from iterator tuple\r
- zip_iterator(IteratorTuple iterator_tuple) \r
- : m_iterator_tuple(iterator_tuple) \r
- { }\r
-\r
- // Copy constructor\r
- template<typename OtherIteratorTuple>\r
- zip_iterator(\r
- const zip_iterator<OtherIteratorTuple>& other,\r
- typename enable_if_convertible<\r
- OtherIteratorTuple,\r
- IteratorTuple\r
- >::type* = 0\r
- ) : m_iterator_tuple(other.get_iterator_tuple())\r
- {}\r
-\r
- // Get method for the iterator tuple.\r
- const IteratorTuple& get_iterator_tuple() const\r
- { return m_iterator_tuple; }\r
-\r
- private:\r
- \r
- // Implementation of Iterator Operations\r
- // =====================================\r
- \r
- // Dereferencing returns a tuple built from the dereferenced\r
- // iterators in the iterator tuple.\r
- typename super_t::reference dereference() const\r
- { \r
- return detail::tuple_impl_specific::tuple_transform( \r
- get_iterator_tuple(),\r
- detail::dereference_iterator()\r
- );\r
- }\r
-\r
- // Two zip iterators are equal if all iterators in the iterator\r
- // tuple are equal. NOTE: It should be possible to implement this\r
- // as\r
- //\r
- // return get_iterator_tuple() == other.get_iterator_tuple();\r
- //\r
- // but equality of tuples currently (7/2003) does not compile\r
- // under several compilers. No point in bringing in a bunch\r
- // of #ifdefs here.\r
- //\r
- template<typename OtherIteratorTuple> \r
- bool equal(const zip_iterator<OtherIteratorTuple>& other) const\r
- {\r
- return detail::tuple_impl_specific::tuple_equal(\r
- get_iterator_tuple(),\r
- other.get_iterator_tuple()\r
- );\r
- }\r
-\r
- // Advancing a zip iterator means to advance all iterators in the\r
- // iterator tuple.\r
- void advance(typename super_t::difference_type n)\r
- { \r
- detail::tuple_impl_specific::tuple_for_each(\r
- m_iterator_tuple,\r
- detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)\r
- );\r
- }\r
- // Incrementing a zip iterator means to increment all iterators in\r
- // the iterator tuple.\r
- void increment()\r
- { \r
- detail::tuple_impl_specific::tuple_for_each(\r
- m_iterator_tuple,\r
- detail::increment_iterator()\r
- );\r
- }\r
- \r
- // Decrementing a zip iterator means to decrement all iterators in\r
- // the iterator tuple.\r
- void decrement()\r
- { \r
- detail::tuple_impl_specific::tuple_for_each(\r
- m_iterator_tuple,\r
- detail::decrement_iterator()\r
- );\r
- }\r
- \r
- // Distance is calculated using the first iterator in the tuple.\r
- template<typename OtherIteratorTuple>\r
- typename super_t::difference_type distance_to(\r
- const zip_iterator<OtherIteratorTuple>& other\r
- ) const\r
- { \r
- return boost::tuples::get<0>(other.get_iterator_tuple()) - \r
- boost::tuples::get<0>(this->get_iterator_tuple());\r
- }\r
- \r
- // Data Members\r
- // ============\r
- \r
- // The iterator tuple.\r
- IteratorTuple m_iterator_tuple;\r
- \r
- };\r
-\r
- // Make function for zip iterator\r
- //\r
- template<typename IteratorTuple> \r
- zip_iterator<IteratorTuple> \r
- make_zip_iterator(IteratorTuple t)\r
- { return zip_iterator<IteratorTuple>(t); }\r
-\r
-}\r
-\r
-#endif\r
+// Copyright David Abrahams and Thomas Becker 2000-2006. 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/detail/iterator.hpp>
+
+#include <boost/iterator/detail/minimum_category.hpp>
+
+#include <boost/tuple/tuple.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/lambda.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost {
+
+ // Zip iterator forward declaration for zip_iterator_base
+ template<typename IteratorTuple>
+ class zip_iterator;
+
+ // One important design goal of the zip_iterator is to isolate all
+ // functionality whose implementation relies on the current tuple
+ // implementation. This goal has been achieved as follows: Inside
+ // the namespace detail there is a namespace tuple_impl_specific.
+ // This namespace encapsulates all functionality that is specific
+ // to the current Boost tuple implementation. More precisely, the
+ // namespace tuple_impl_specific provides the following tuple
+ // algorithms and meta-algorithms for the current Boost tuple
+ // implementation:
+ //
+ // tuple_meta_transform
+ // tuple_meta_accumulate
+ // tuple_transform
+ // tuple_for_each
+ //
+ // If the tuple implementation changes, all that needs to be
+ // replaced is the implementation of these four (meta-)algorithms.
+
+ 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)
+ { ++it; }
+ };
+ //
+ struct decrement_iterator
+ {
+ template<typename Iterator>
+ void operator()(Iterator& it)
+ { --it; }
+ };
+ //
+ struct dereference_iterator
+ {
+ template<typename Iterator>
+ struct apply
+ {
+ typedef typename
+ iterator_traits<Iterator>::reference
+ type;
+ };
+
+ template<typename Iterator>
+ typename apply<Iterator>::type operator()(Iterator const& it)
+ { return *it; }
+ };
+
+
+ // The namespace tuple_impl_specific provides two meta-
+ // algorithms and two algorithms for tuples.
+ //
+ namespace tuple_impl_specific
+ {
+ // Meta-transform algorithm for tuples
+ //
+ template<typename Tuple, class UnaryMetaFun>
+ struct tuple_meta_transform;
+
+ template<typename Tuple, class UnaryMetaFun>
+ struct tuple_meta_transform_impl
+ {
+ typedef tuples::cons<
+ typename mpl::apply1<
+ typename mpl::lambda<UnaryMetaFun>::type
+ , typename Tuple::head_type
+ >::type
+ , typename tuple_meta_transform<
+ typename Tuple::tail_type
+ , UnaryMetaFun
+ >::type
+ > type;
+ };
+
+ template<typename Tuple, class UnaryMetaFun>
+ struct tuple_meta_transform
+ : mpl::eval_if<
+ boost::is_same<Tuple, tuples::null_type>
+ , mpl::identity<tuples::null_type>
+ , tuple_meta_transform_impl<Tuple, UnaryMetaFun>
+ >
+ {
+ };
+
+ // Meta-accumulate algorithm for tuples. Note: The template
+ // parameter StartType corresponds to the initial value in
+ // ordinary accumulation.
+ //
+ template<class Tuple, class BinaryMetaFun, class StartType>
+ struct tuple_meta_accumulate;
+
+ template<
+ typename Tuple
+ , class BinaryMetaFun
+ , typename StartType
+ >
+ struct tuple_meta_accumulate_impl
+ {
+ typedef typename mpl::apply2<
+ typename mpl::lambda<BinaryMetaFun>::type
+ , typename Tuple::head_type
+ , typename tuple_meta_accumulate<
+ typename Tuple::tail_type
+ , BinaryMetaFun
+ , StartType
+ >::type
+ >::type type;
+ };
+
+ template<
+ typename Tuple
+ , class BinaryMetaFun
+ , typename StartType
+ >
+ struct tuple_meta_accumulate
+ : mpl::eval_if<
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ mpl::or_<
+#endif
+ boost::is_same<Tuple, tuples::null_type>
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ , boost::is_same<Tuple,int>
+ >
+#endif
+ , mpl::identity<StartType>
+ , tuple_meta_accumulate_impl<
+ Tuple
+ , BinaryMetaFun
+ , StartType
+ >
+ >
+ {
+ };
+
+#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ || ( \
+ BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \
+ )
+// Not sure why intel's partial ordering fails in this case, but I'm
+// assuming int's an MSVC bug-compatibility feature.
+
+# define BOOST_TUPLE_ALGO_DISPATCH
+# define BOOST_TUPLE_ALGO(algo) algo##_impl
+# define BOOST_TUPLE_ALGO_TERMINATOR , int
+# define BOOST_TUPLE_ALGO_RECURSE , ...
+#else
+# define BOOST_TUPLE_ALGO(algo) algo
+# define BOOST_TUPLE_ALGO_TERMINATOR
+# define BOOST_TUPLE_ALGO_RECURSE
+#endif
+
+ // transform algorithm for tuples. The template parameter Fun
+ // must be a unary functor which is also a unary metafunction
+ // class that computes its return type based on its argument
+ // type. For example:
+ //
+ // struct to_ptr
+ // {
+ // template <class Arg>
+ // struct apply
+ // {
+ // typedef Arg* type;
+ // }
+ //
+ // template <class Arg>
+ // Arg* operator()(Arg x);
+ // };
+ template<typename Fun>
+ tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
+ (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
+ { return tuples::null_type(); }
+
+ template<typename Tuple, typename Fun>
+ typename tuple_meta_transform<
+ Tuple
+ , Fun
+ >::type
+
+ BOOST_TUPLE_ALGO(tuple_transform)(
+ const Tuple& t,
+ Fun f
+ BOOST_TUPLE_ALGO_RECURSE
+ )
+ {
+ typedef typename tuple_meta_transform<
+ BOOST_DEDUCED_TYPENAME Tuple::tail_type
+ , Fun
+ >::type transformed_tail_type;
+
+ return tuples::cons<
+ BOOST_DEDUCED_TYPENAME mpl::apply1<
+ Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
+ >::type
+ , transformed_tail_type
+ >(
+ f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
+ );
+ }
+
+#ifdef BOOST_TUPLE_ALGO_DISPATCH
+ template<typename Tuple, typename Fun>
+ typename tuple_meta_transform<
+ Tuple
+ , Fun
+ >::type
+
+ tuple_transform(
+ const Tuple& t,
+ Fun f
+ )
+ {
+ return tuple_transform_impl(t, f, 1);
+ }
+#endif
+
+ // for_each algorithm for tuples.
+ //
+ template<typename Fun>
+ Fun BOOST_TUPLE_ALGO(tuple_for_each)(
+ tuples::null_type
+ , Fun f BOOST_TUPLE_ALGO_TERMINATOR
+ )
+ { return f; }
+
+
+ template<typename Tuple, typename Fun>
+ Fun BOOST_TUPLE_ALGO(tuple_for_each)(
+ Tuple& t
+ , Fun f BOOST_TUPLE_ALGO_RECURSE)
+ {
+ f( t.get_head() );
+ return tuple_for_each(t.get_tail(), f);
+ }
+
+#ifdef BOOST_TUPLE_ALGO_DISPATCH
+ template<typename Tuple, typename Fun>
+ Fun
+ tuple_for_each(
+ Tuple& t,
+ Fun f
+ )
+ {
+ return tuple_for_each_impl(t, f, 1);
+ }
+#endif
+
+ // Equality of tuples. NOTE: "==" for tuples currently (7/2003)
+ // has problems under some compilers, so I just do my own.
+ // No point in bringing in a bunch of #ifdefs here. This is
+ // going to go away with the next tuple implementation anyway.
+ //
+ inline bool tuple_equal(tuples::null_type, tuples::null_type)
+ { return true; }
+
+ template<typename Tuple1, typename Tuple2>
+ bool tuple_equal(
+ Tuple1 const& t1,
+ Tuple2 const& t2
+ )
+ {
+ return t1.get_head() == t2.get_head() &&
+ tuple_equal(t1.get_tail(), t2.get_tail());
+ }
+ }
+ //
+ // end namespace tuple_impl_specific
+
+ template<typename Iterator>
+ struct iterator_reference
+ {
+ typedef typename iterator_traits<Iterator>::reference type;
+ };
+
+#ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+ // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
+ // out well. Instantiating the nested apply template also
+ // requires instantiating iterator_traits on the
+ // placeholder. Instead we just specialize it as a metafunction
+ // class.
+ template<>
+ struct iterator_reference<mpl::_1>
+ {
+ template <class T>
+ struct apply : iterator_reference<T> {};
+ };
+#endif
+
+ // 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
+ : tuple_impl_specific::tuple_meta_transform<
+ IteratorTuple,
+ iterator_reference<mpl::_1>
+ >
+ {
+ };
+
+ // Metafunction to obtain the minimal traversal tag in a tuple
+ // of iterators.
+ //
+ template<typename IteratorTuple>
+ struct minimum_traversal_category_in_iterator_tuple
+ {
+ typedef typename tuple_impl_specific::tuple_meta_transform<
+ IteratorTuple
+ , iterator_traversal<>
+ >::type tuple_of_traversal_tags;
+
+ typedef typename tuple_impl_specific::tuple_meta_accumulate<
+ tuple_of_traversal_tags
+ , minimum_category<>
+ , random_access_traversal_tag
+ >::type type;
+ };
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround
+ template <>
+ struct minimum_traversal_category_in_iterator_tuple<int>
+ {
+ typedef int type;
+ };
+#endif
+
+ // We need to call tuple_meta_accumulate with mpl::and_ as the
+ // accumulating functor. To this end, we need to wrap it into
+ // a struct that has exactly two arguments (that is, template
+ // parameters) and not five, like mpl::and_ does.
+ //
+ template<typename Arg1, typename Arg2>
+ struct and_with_two_args
+ : mpl::and_<Arg1, Arg2>
+ {
+ };
+
+# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+ // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
+ // out well. In this case I think it's an MPL bug
+ template<>
+ struct and_with_two_args<mpl::_1,mpl::_2>
+ {
+ template <class A1, class A2>
+ struct apply : mpl::and_<A1,A2>
+ {};
+ };
+# endif
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // 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_traits<
+ typename tuples::element<0, IteratorTuple>::type
+ >::difference_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;
+ };
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ //
+ // 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
+ {
+ return detail::tuple_impl_specific::tuple_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 detail::tuple_impl_specific::tuple_equal(
+ 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)
+ {
+ detail::tuple_impl_specific::tuple_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()
+ {
+ detail::tuple_impl_specific::tuple_for_each(
+ m_iterator_tuple,
+ detail::increment_iterator()
+ );
+ }
+
+ // Decrementing a zip iterator means to decrement all iterators in
+ // the iterator tuple.
+ void decrement()
+ {
+ detail::tuple_impl_specific::tuple_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 boost::tuples::get<0>(other.get_iterator_tuple()) -
+ boost::tuples::get<0>(this->get_iterator_tuple());
+ }
+
+ // Data Members
+ // ============
+
+ // The iterator tuple.
+ IteratorTuple m_iterator_tuple;
+
+ };
+
+ // Make function for zip iterator
+ //
+ template<typename IteratorTuple>
+ zip_iterator<IteratorTuple>
+ make_zip_iterator(IteratorTuple t)
+ { return zip_iterator<IteratorTuple>(t); }
+
+}
+
+#endif