Compare commits

...

39 Commits

Author SHA1 Message Date
22dd100dfd Revert "Remove unused deprecated includes"
This reverts commit b2b9ab1568.
2015-10-15 23:55:35 -04:00
2f72016049 Revert "Fix test compilation"
This reverts commit 443dfb9901.
2015-10-15 23:53:37 -04:00
5b26a8b3fc Merge branch 'develop' 2015-10-14 23:59:55 -04:00
711a0232f8 Merge pull request #19 from MarcelRaad/patch-1
Fix test compilation
2015-09-22 18:03:05 -07:00
443dfb9901 Fix test compilation
boost/iterator.hpp was implicitly dragged in via boost/operators.hpp, from which it was removed in cb6500161b. It's not needed anyway, all it does is map boost::iterator to std::iterator.
2015-09-22 00:33:50 +02:00
c734f3bfa3 Merge pull request #18 from MarcelRaad/remove-deprecated-includes
Remove deprecated includes
2015-09-14 12:06:20 -04:00
b2b9ab1568 Remove unused deprecated includes
A comment in boost/iterator.hpp and boost/detail/iterator.hpp mentions that
the files are obsolete and will be deprecated. All they do is pull some types
from namespace std into namespace boost.
2015-09-14 14:28:38 +02:00
8b23342969 Merge pull request #17 from boostorg/revert-16-remove-deprecated-includes
Revert "Remove unused deprecated includes"
2015-09-14 08:17:35 -04:00
922296f8c8 Revert "Remove unused deprecated includes" 2015-09-14 08:16:43 -04:00
c9a91a1fba Merge pull request #16 from MarcelRaad/remove-deprecated-includes
Remove unused deprecated includes
2015-09-14 08:08:53 -04:00
80e6f4a3bf Remove unused deprecated includes
A comment in boost/iterator.hpp and boost/detail/iterator.hpp mentions that
the files are obsolete and will be deprecated. All they do is pull some types
from namespace std into namespace boost.
2015-09-14 10:57:16 +02:00
398bbe63bb Updated quickbook docs just fix problems exposed by upgrading to quickbook 1.6 2015-08-24 12:49:59 -04:00
87d82527b1 Updated zip iterator abstract adds information about the iterator 'tuple'. 2015-08-24 07:18:03 -04:00
b9448b5fae Updated with an explanation of the new 'tuple' type for a zip_iterator based on Boost fusion sequences. 2015-08-24 00:24:09 -04:00
76519ea4a7 Merge branch 'Flast-pr/zip_iterator/fusionize' into develop 2015-08-23 23:56:13 -04:00
878812c42f More tests with fusion sequence as tuple 2015-08-23 23:46:44 -04:00
2283f084d9 Merge pull request #2 from Flast/pr/zip_iterator/fusionize
Fusion based zip_iterator, close #7526
2015-08-23 23:37:38 -04:00
a0533d97f5 Merge branch 'pr/zip_iterator/fusionize' of https://github.com/Flast/iterator into Flast-pr/zip_iterator/fusionize 2015-08-21 22:09:37 -04:00
ece225bbda Merge branch 'develop' 2015-07-18 22:08:52 -04:00
b62dc6ba9d Remove unneeded header file for undefines. 2015-05-22 00:54:44 -04:00
20dc7b1abe Merge pull request #14 from eldiener/develop
Changed needed for type_traits version2 to remove icexxx.hpp dependencies.
2015-05-21 23:28:00 -04:00
0dbbb61bec Put back MPL auxiliary lambda support. 2015-05-21 23:15:31 -04:00
2de2111db2 Remove dependency on deprecated type_traits headers. 2015-05-21 23:14:42 -04:00
db04fafe21 Merge pull request #12 from Lastique/patch-1
Remove unused pure_traversal_tag import into boost::iterators::detail
2015-05-21 16:52:07 -04:00
4e0fc90b60 Merge pull request #11 from jzmaddock/patch-1
Update is_lvalue_iterator.hpp
2015-05-21 16:35:38 -04:00
53cbba6c09 Remove unused name import
As Boost.Range has been updated, there is no need to import pure_traversal_tag into boost::iterators::detail.
2015-01-26 00:02:36 +03:00
8be623d733 Update is_lvalue_iterator.hpp 2015-01-22 08:48:25 +00:00
d12d60fa12 Update is_lvalue_iterator.hpp
In the current type_traits rewrite, type_traits headers no long implicitly include mpl ones, so mpl/bool.hpp has to be explicitly included now.
2015-01-21 16:54:54 +00:00
ec7d398578 Merge pull request #10 from Flast/pr/ref-to-ref/dr106
Avoid 'reference to reference' error with strict C++03 compiler.

While I can't reproduce the error you describe, the patch looks good and it tested okay with Clang 6.0 on Mac and gcc-4.9.1 on Linux.  Thanks for the patch.
2014-11-02 15:59:02 -07:00
3d3560c12d Avoid 'reference to reference' error in C++03.
Some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject
  'reference-to-reference' in the template and typedef which described
  in CWG DR106 [1].

  In such situations, iterator_facade rejects reference type as a value
  type and some special iterators will become ill-formed:
  the test libs/range/test/join.hpp might be descriptive.

  [1] http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106

Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-09-29 14:58:40 +09:00
2511f21d62 Merge upstream branch 'develop' into pr/zip_iterator/fusionize 2014-08-25 00:36:36 +09:00
156c13a494 Merge upstream branch 'develop' into pr/zip_iterator/fusionize
Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-07-12 15:57:03 +09:00
11f7d1bc18 Merge upstream branch 'develop' into pr/zip_iterator/fusionize
Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-07-03 21:52:26 +09:00
aad767ed3f Merge upstream branch 'develop' into pr/zip_iterator/fusionize 2014-06-30 11:13:38 +09:00
9841d87212 Add tests for fusion based zip_iterator
Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-06-14 15:59:31 +09:00
782313db8c Remove unnecessary specialization
Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-06-14 15:59:31 +09:00
c040d4c38b make_zip_iterator should be inlined
Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-06-14 15:59:31 +09:00
1ddaca8297 zip_iterator specialization for std::pair
Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-06-14 15:59:31 +09:00
acf9b4d4cf Reimplement zip_iterator based on Boost.Fusion
By default, backward compatibility for Boost.Tuple is presented.

Signed-off-by: Kohei Takahashi <flast@flast.jp>
2014-06-12 01:05:36 +09:00
31 changed files with 1341 additions and 1226 deletions

View File

@ -132,7 +132,7 @@ above are defined as follows:
iterator_adaptor();
[*Requires:] The `Base` type must be Default Constructible.\n
[*Requires:] The `Base` type must be Default Constructible.[br]
[*Returns:] An instance of `iterator_adaptor` with
`m_iterator` default constructed.
@ -206,7 +206,7 @@ we're going to pick up right where it left off.
.. |fac_tut| replace:: `iterator_facade` tutorial
.. _fac_tut: iterator_facade.html#tutorial-example
[blurb [*`node_base*` really *is* an iterator]\n\n
[blurb [*`node_base*` really *is* an iterator][br][br]
It's not really a very interesting iterator, since `node_base`
is an abstract class: a pointer to a `node_base` just points
at some base subobject of an instance of some other class, and

View File

@ -156,7 +156,7 @@ semantics.
[
[`++r`]
[`X&`]
[pre:\n`r` is dereferenceable;\npost:\n`r` is dereferenceable or\n`r` is past-the-end]
[pre:[br]`r` is dereferenceable;[br]post:[br]`r` is dereferenceable or[br]`r` is past-the-end]
]
[
[`a == b`]
@ -227,7 +227,7 @@ the stated semantics.
[
[`--r`]
[`X&`]
[pre: there exists `s` such that `r == ++s`.\n post: `s` is dereferenceable. `--(++r) == r`. `--r == --s` implies `r == s`. `&r == &--r`.]
[pre: there exists `s` such that `r == ++s`.[br] post: `s` is dereferenceable. `--(++r) == r`. `--r == --s` implies `r == s`. `&r == &--r`.]
]
[
[`r--`]

View File

@ -152,7 +152,7 @@ operations.
counting_iterator();
[*Requires: ] `Incrementable` is Default Constructible.\n
[*Requires: ] `Incrementable` is Default Constructible.[br]
[*Effects: ] Default construct the member `m_inc`.
@ -174,13 +174,13 @@ operations.
counting_iterator& operator++();
[*Effects: ] `++m_inc`\n
[*Effects: ] `++m_inc`[br]
[*Returns: ] `*this`
counting_iterator& operator--();
[*Effects: ] `--m_inc`\n
[*Effects: ] `--m_inc`[br]
[*Returns: ] `*this`

View File

@ -68,6 +68,7 @@ requirements.
[
[`i.dereference()`]
[Access the value referred to]
]
[
[`i.equal(j)`]
[Compare for equality with `j`]
@ -83,6 +84,7 @@ requirements.
[
[`i.advance(n)`]
[Advance by `n` positions]
]
[
[`i.distance_to(j)`]
[Measure the distance to `j`]
@ -487,7 +489,8 @@ w.m)` for some temporary object `w` of type `value_type`.
iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -495,6 +498,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`((Dr2 const&)rhs).equal((Dr1 const&)lhs)`.
]
template <class Dr1, class V1, class TC1, class R1, class D1,
@ -505,6 +509,7 @@ w.m)` for some temporary object `w` of type `value_type`.
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -512,6 +517,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`!((Dr2 const&)rhs).equal((Dr1 const&)lhs)`.
]
template <class Dr1, class V1, class TC1, class R1, class D1,
@ -522,6 +528,7 @@ w.m)` for some temporary object `w` of type `value_type`.
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -529,6 +536,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0`.
]
template <class Dr1, class V1, class TC1, class R1, class D1,
@ -539,6 +547,7 @@ w.m)` for some temporary object `w` of type `value_type`.
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -546,6 +555,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0`.
]
template <class Dr1, class V1, class TC1, class R1, class D1,
@ -556,6 +566,7 @@ w.m)` for some temporary object `w` of type `value_type`.
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -563,6 +574,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0`.
]
template <class Dr1, class V1, class TC1, class R1, class D1,
@ -573,6 +585,7 @@ w.m)` for some temporary object `w` of type `value_type`.
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -580,6 +593,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0`.
]
.. _minus:
@ -592,6 +606,7 @@ w.m)` for some temporary object `w` of type `value_type`.
[*Return Type:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -600,9 +615,11 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise
`difference` shall be `iterator_traits<Dr2>::difference_type`
]
[*Returns:]
[pre
if `is_convertible<Dr2,Dr1>::value`
then
@ -610,6 +627,7 @@ w.m)` for some temporary object `w` of type `value_type`.
Otherwise,
`((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)`.
]
[endsect]

View File

@ -261,17 +261,17 @@ __ ../example/node_iterator1.cpp
[h2 A constant `node_iterator`]
[blurb *Constant and Mutable iterators*\n\n
[blurb *Constant and Mutable iterators*[br][br]
The term **mutable iterator** means an iterator through which
the object it references (its "referent") can be modified. A
**constant iterator** is one which doesn't allow modification of
its referent.\n\n
its referent.[br][br]
The words *constant* and *mutable* don't refer to the ability to
modify the iterator itself. For example, an `int const*` is a
non-\ `const` *constant iterator*, which can be incremented
but doesn't allow modification of its referent, and `int*
const` is a `const` *mutable iterator*, which cannot be
modified but which allows modification of its referent.\n\n
modified but which allows modification of its referent.[br][br]
Confusing? We agree, but those are the standard terms. It
probably doesn't help much that a container's constant iterator
is called `const_iterator`.
@ -312,7 +312,7 @@ changes:
node_base **const**\ * m_node;
};
[blurb `const` and an iterator's `value_type`\n\n
[blurb `const` and an iterator's `value_type`[br][br]
The C++ standard requires an iterator's `value_type` *not* be
`const`\ -qualified, so `iterator_facade` strips the
`const` from its `Value` parameter in order to produce the

View File

@ -178,7 +178,7 @@ operations.
filter_iterator();
[*Requires: ]`Predicate` and `Iterator` must be Default Constructible.\n
[*Requires: ]`Predicate` and `Iterator` must be Default Constructible.[br]
[*Effects: ] Constructs a `filter_iterator` whose`m_pred`, `m_iter`, and `m_end`
members are a default constructed.
@ -195,7 +195,7 @@ operations.
filter_iterator(Iterator x, Iterator end = Iterator());
[*Requires: ] `Predicate` must be Default Constructible and
`Predicate` is a class type (not a function pointer).\n
`Predicate` is a class type (not a function pointer).[br]
[*Effects: ] Constructs a `filter_iterator` where `m_iter` is either
the first position in the range `[x,end)` such that `m_pred(*m_iter) == true`
or else`m_iter == end`. The member `m_pred` is default constructed.
@ -205,9 +205,9 @@ operations.
filter_iterator(
filter_iterator<Predicate, OtherIterator> const& t
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
);`
);
[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.\n
[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.[br]
[*Effects: ] Constructs a filter iterator whose members are copied from `t`.
@ -235,7 +235,7 @@ operations.
[*Effects: ] Increments `m_iter` and then continues to
increment `m_iter` until either `m_iter == m_end`
or `m_pred(*m_iter) == true`.\n
or `m_pred(*m_iter) == true`.[br]
[*Returns: ] `*this`

View File

@ -203,7 +203,7 @@ following operations:
indirect_iterator();
[*Requires: ] `Iterator` must be Default Constructible.\n
[*Requires: ] `Iterator` must be Default Constructible.[br]
[*Effects: ] Constructs an instance of `indirect_iterator` with
a default-constructed `m_iterator`.
@ -225,7 +225,7 @@ following operations:
, typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
);
[*Requires: ] `Iterator2` is implicitly convertible to `Iterator`.\n
[*Requires: ] `Iterator2` is implicitly convertible to `Iterator`.[br]
[*Effects: ] Constructs an instance of `indirect_iterator` whose
`m_iterator` subobject is constructed from `y.base()`.
@ -242,13 +242,13 @@ following operations:
indirect_iterator& operator++();
[*Effects: ] `++m_iterator`\n
[*Effects: ] `++m_iterator`[br]
[*Returns: ] `*this`
indirect_iterator& operator--();
[*Effects: ] `--m_iterator`\n
[*Effects: ] `--m_iterator`[br]
[*Returns: ] `*this`
[endsect]

View File

@ -1,6 +1,7 @@
[library Boost.Iterator
[/ version 1.0.1]
[quickbook 1.6]
[authors [Abrahams, David], [Siek, Jeremy], [Witt, Thomas]]
[copyright 2003 2005 David Abrahams Jeremy Siek Thomas Witt]
[category iterator]
@ -99,7 +100,7 @@ adaptors`_ mentioned below have been proposed for standardization
The iterator library supplies a useful suite of standard-conforming
iterator templates based on the Boost [link
intro.iterator_facade_and_adaptor iterator facade and adaptor]
iterator.intro.iterator_facade_and_adaptor iterator facade and adaptor]
templates.
[def _counting_ [@./counting_iterator.html `counting_iterator`]]

View File

@ -189,7 +189,7 @@ following operations.
permutation_iterator& operator++();
[*Effects: ] `++m_order`\n
[*Effects: ] `++m_order`[br]
[*Returns: ] `*this`

View File

@ -115,7 +115,7 @@ operations.
reverse_iterator();
[*Requires: ] `Iterator` must be Default Constructible.\n
[*Requires: ] `Iterator` must be Default Constructible.[br]
[*Effects: ] Constructs an instance of `reverse_iterator` with `m_iterator`
default constructed.
@ -131,7 +131,7 @@ operations.
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
);
[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.\n
[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.[br]
[*Effects: ] Constructs instance of `reverse_iterator` whose
`m_iterator` subobject is constructed from `y.base()`.
@ -149,12 +149,12 @@ operations.
reverse_iterator& operator++();
[*Effects: ] `--m_iterator`\n
[*Effects: ] `--m_iterator`[br]
[*Returns: ] `*this`
reverse_iterator& operator--();
[*Effects: ] `++m_iterator`\n
[*Effects: ] `++m_iterator`[br]
[*Returns: ] `*this`
[endsect]

View File

@ -85,7 +85,7 @@ The source code for this example can be found
If `Reference` is `use_default` then the `reference` member of
`transform_iterator` is\n
`transform_iterator` is[br]
`result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type`.
Otherwise, `reference` is `Reference`.
@ -160,7 +160,7 @@ interoperable with `Y`.
[h3 Operations]
In addition to the operations required by the [link transform.concepts concepts] modeled by
In addition to the operations required by the [link iterator.specialized.transform.concepts concepts] modeled by
`transform_iterator`, `transform_iterator` provides the following
operations:
@ -183,7 +183,7 @@ operations:
[*Returns: ] An instance of `transform_iterator` with `m_f`
initialized to `t.functor()` and `m_iterator` initialized to
`t.base()`.\n
`t.base()`.[br]
[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.
@ -204,13 +204,13 @@ operations:
transform_iterator& operator++();
[*Effects: ] `++m_iterator`\n
[*Effects: ] `++m_iterator`[br]
[*Returns: ] `*this`
transform_iterator& operator--();
[*Effects: ] `--m_iterator`\n
[*Effects: ] `--m_iterator`[br]
[*Returns: ] `*this`
[endsect]

View File

@ -49,7 +49,7 @@ proxy references or return the pointee by value. When that
information is needed, call on `indirect_reference`.
Both of these templates are essential to the correct functioning of
[link boost_iterator.indirect `indirect_iterator`].
[link iterator.specialized.indirect `indirect_iterator`].
[h2 `minimum_category`]
@ -103,9 +103,9 @@ or not), these additional tags are not considered.
if ( ++x is ill-formed )
{
return `Dereferenceable::element_type`
return Dereferenceable::element_type
}
else if (`*x` is a mutable reference to
else if (*x is a mutable reference to
std::iterator_traits<Dereferenceable>::value_type)
{
return iterator_traits<Dereferenceable>::value_type
@ -135,7 +135,7 @@ or not), these additional tags are not considered.
`x` is an object of type `Dereferenceable`:
if ( ++x is ill-formed )
return `pointee<Dereferenceable>::type&`
return pointee<Dereferenceable>::type&
else
std::iterator_traits<Dereferenceable>::reference

View File

@ -8,6 +8,16 @@ the zip iterator moves all the iterators in parallel.
Dereferencing the zip iterator returns a tuple that contains
the results of dereferencing the individual iterators.
The tuple of iterators is now implemented in terms of a Boost fusion sequence.
Because of this the 'tuple' may be any Boost fusion sequence and, for backwards
compatibility through a Boost fusion sequence adapter, a Boost tuple. Because the
'tuple' may be any boost::fusion sequence the 'tuple' may also be any type for which a
Boost fusion adapter exists. This includes, among others, a std::tuple and a std::pair.
Just remember to include the appropriate Boost fusion adapter header files for these
other Boost fusion adapters. The zip_iterator header file already includes the
Boost fusion adapter header file for Boost tuple, so you need not include it yourself
to use a Boost tuple as your 'tuple'.
[section:zip_example Example]
There are two main types of applications of the `zip_iterator`. The first
@ -218,7 +228,7 @@ operations.
, IteratorTuple>::type* = 0 // exposition only
);
[*Returns:] An instance of `zip_iterator` that is a copy of `other`.\n
[*Returns:] An instance of `zip_iterator` that is a copy of `other`.[br]
[*Requires:] `OtherIteratorTuple` is implicitly convertible to `IteratorTuple`.
@ -235,13 +245,13 @@ operations.
zip_iterator& operator++();
[*Effects:] Increments each iterator in `m_iterator_tuple`.\n
[*Effects:] Increments each iterator in `m_iterator_tuple`.[br]
[*Returns:] `*this`
zip_iterator& operator--();
[*Effects:] Decrements each iterator in `m_iterator_tuple`.\n
[*Effects:] Decrements each iterator in `m_iterator_tuple`.[br]
[*Returns:] `*this`
template<typename IteratorTuple>

View File

@ -8,3 +8,13 @@ iterator is constructed from a tuple of iterators. Moving
the zip iterator moves all the iterators in parallel.
Dereferencing the zip iterator returns a tuple that contains
the results of dereferencing the individual iterators.
The tuple of iterators is now implemented in terms of a Boost fusion sequence.
Because of this the 'tuple' may be any Boost fusion sequence and, for backwards
compatibility through a Boost fusion sequence adapter, a Boost tuple. Because the
'tuple' may be any boost::fusion sequence the 'tuple' may also be any type for which a
Boost fusion adapter exists. This includes, among others, a std::tuple and a std::pair.
Just remember to include the appropriate Boost fusion adapter header files for these
other Boost fusion adapters. The zip_iterator header file already includes the
Boost fusion adapter header file for Boost tuple, so you need not include it yourself
to use a Boost tuple as your 'tuple'.

View File

@ -9,10 +9,13 @@
#include <boost/detail/workaround.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/iterator/detail/any_conversion_eater.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
// should be the last #includes
#include <boost/type_traits/detail/bool_trait_def.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
@ -52,7 +55,7 @@ namespace detail
// convertible to Value const&
struct conversion_eater
{
conversion_eater(Value&);
conversion_eater(typename add_lvalue_reference<Value>::type);
};
static char tester(conversion_eater, int);
@ -134,13 +137,19 @@ namespace detail
{};
} // namespace detail
// Define the trait with full mpl lambda capability and various broken
// compiler workarounds
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_lvalue_iterator,T,::boost::iterators::detail::is_readable_lvalue_iterator_impl<T>::value)
template< typename T > struct is_lvalue_iterator
: public ::boost::integral_constant<bool,::boost::iterators::detail::is_readable_lvalue_iterator_impl<T>::value>
{
public:
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_lvalue_iterator,(T))
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_non_const_lvalue_iterator,T,::boost::iterators::detail::is_non_const_lvalue_iterator_impl<T>::value)
template< typename T > struct is_non_const_lvalue_iterator
: public ::boost::integral_constant<bool,::boost::iterators::detail::is_non_const_lvalue_iterator_impl<T>::value>
{
public:
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_non_const_lvalue_iterator,(T))
};
} // namespace iterators
@ -152,6 +161,5 @@ using iterators::is_non_const_lvalue_iterator;
#endif
#include <boost/iterator/detail/config_undef.hpp>
#include <boost/type_traits/detail/bool_trait_undef.hpp>
#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP

View File

@ -5,12 +5,14 @@
# define IS_READABLE_ITERATOR_DWA2003112_HPP
#include <boost/mpl/bool.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/type_traits/detail/bool_trait_def.hpp>
#include <boost/iterator/detail/any_conversion_eater.hpp>
// should be the last #include
#include <boost/type_traits/integral_constant.hpp>
#include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
@ -26,7 +28,7 @@ namespace detail
template <class Value>
struct is_readable_iterator_impl
{
static char tester(Value&, int);
static char tester(typename add_lvalue_reference<Value>::type, int);
static char (& tester(any_conversion_eater, ...) )[2];
template <class It>
@ -96,10 +98,12 @@ namespace detail
{};
} // namespace detail
// Define the trait with full mpl lambda capability and various broken
// compiler workarounds
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_readable_iterator,T,::boost::iterators::detail::is_readable_iterator_impl2<T>::value)
template< typename T > struct is_readable_iterator
: public ::boost::integral_constant<bool,::boost::iterators::detail::is_readable_iterator_impl2<T>::value>
{
public:
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_readable_iterator,(T))
};
} // namespace iterators

View File

@ -168,13 +168,6 @@ struct pure_traversal_tag
{
};
// This import is needed for backward compatibility with Boost.Range:
// boost/range/detail/demote_iterator_traversal_tag.hpp
// It should be removed when that header is fixed.
namespace detail {
using iterators::pure_traversal_tag;
} // namespace detail
//
// Trait to retrieve one of the iterator traversal tags from the iterator category or traversal.
//

View File

@ -22,6 +22,7 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_convertible.hpp>
@ -284,7 +285,15 @@ namespace iterators {
: mpl::eval_if<
mpl::and_<
// A proxy is only needed for readable iterators
is_convertible<Reference,Value const&>
is_convertible<
Reference
// Use add_lvalue_reference to form `reference to Value` due to
// some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject
// 'reference-to-reference' in the template which described in CWG
// DR106.
// http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106
, typename add_lvalue_reference<Value const>::type
>
// No multipass iterator can have values that disappear
// before positions can be re-visited

View File

@ -1,6 +1,8 @@
// 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
// 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_
@ -12,19 +14,26 @@
#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/minimum_category.hpp>
#include <boost/tuple/tuple.hpp>
#include <utility> // for std::pair
#include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
#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/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/mpl/aux_/lambda_support.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 {
@ -33,24 +42,6 @@ namespace iterators {
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
{
@ -73,313 +64,96 @@ namespace iterators {
struct increment_iterator
{
template<typename Iterator>
void operator()(Iterator& it)
void operator()(Iterator& it) const
{ ++it; }
};
//
struct decrement_iterator
{
template<typename Iterator>
void operator()(Iterator& it)
void operator()(Iterator& it) const
{ --it; }
};
//
struct dereference_iterator
{
template<typename Iterator>
struct apply
template<typename>
struct result;
template<typename This, typename Iterator>
struct result<This(Iterator)>
{
typedef typename
boost::detail::iterator_traits<Iterator>::reference
type;
remove_reference<typename remove_cv<Iterator>::type>::type
iterator;
typedef typename iterator_reference<iterator>::type type;
};
template<typename Iterator>
typename apply<Iterator>::type operator()(Iterator const& it)
typename result<dereference_iterator(Iterator)>::type
operator()(Iterator const& it) const
{ 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<
boost::is_same<Tuple, tuples::null_type>
, 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>
inline 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>
inline 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>
inline 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>
inline Fun BOOST_TUPLE_ALGO(tuple_for_each)(
tuples::null_type
, Fun f BOOST_TUPLE_ALGO_TERMINATOR
)
{ return f; }
template<typename Tuple, typename Fun>
inline 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>
inline 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>
inline 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 boost::detail::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<
: 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 tuple_impl_specific::tuple_meta_transform<
typedef typename mpl::transform<
IteratorTuple
, pure_traversal_tag<iterator_traversal<> >
>::type tuple_of_traversal_tags;
typedef typename tuple_impl_specific::tuple_meta_accumulate<
typedef typename mpl::fold<
tuple_of_traversal_tags
, minimum_category<>
, random_access_traversal_tag
, minimum_category<>
>::type type;
};
// 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>
{
};
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;
# 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
typedef typename minimum_category<
iterator1_traversal
, typename minimum_category<
iterator2_traversal
, random_access_traversal_tag
>::type
>::type type;
};
///////////////////////////////////////////////////////////////////
//
@ -401,9 +175,9 @@ namespace iterators {
typedef reference value_type;
// Difference type is the first iterator's difference type
typedef typename boost::detail::iterator_traits<
typename tuples::element<0, IteratorTuple>::type
>::difference_type 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.
@ -429,6 +203,30 @@ namespace iterators {
{
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));
}
};
}
/////////////////////////////////////////////////////////////////////
@ -484,10 +282,11 @@ namespace iterators {
// iterators in the iterator tuple.
typename super_t::reference dereference() const
{
return detail::tuple_impl_specific::tuple_transform(
get_iterator_tuple(),
detail::dereference_iterator()
);
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
@ -503,39 +302,35 @@ namespace iterators {
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()
);
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)
{
detail::tuple_impl_specific::tuple_for_each(
fusion::for_each(
m_iterator_tuple,
detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
);
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()
);
fusion::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()
);
fusion::for_each(
m_iterator_tuple,
detail::decrement_iterator());
}
// Distance is calculated using the first iterator in the tuple.
@ -544,8 +339,8 @@ namespace iterators {
const zip_iterator<OtherIteratorTuple>& other
) const
{
return boost::tuples::get<0>(other.get_iterator_tuple()) -
boost::tuples::get<0>(this->get_iterator_tuple());
return fusion::at_c<0>(other.get_iterator_tuple()) -
fusion::at_c<0>(this->get_iterator_tuple());
}
// Data Members

View File

@ -14,11 +14,17 @@ test-suite iterator
[ run zip_iterator_test.cpp
: : :
# stlport's debug mode generates long symbols which overwhelm
# vc6
#<msvc-stlport><*><runtime-build>release
]
[ run zip_iterator_test2_std_tuple.cpp ]
[ run zip_iterator_test2_fusion_vector.cpp ]
[ run zip_iterator_test2_fusion_list.cpp ]
# [ run zip_iterator_test2_fusion_deque.cpp ] // See bug report for fusion https://svn.boost.org/trac/boost/ticket/11572
[ run zip_iterator_test_fusion.cpp ]
[ run zip_iterator_test_std_tuple.cpp ]
[ run zip_iterator_test_std_pair.cpp ]
# These tests should work for just about everything.
[ compile is_lvalue_iterator.cpp ]

View File

@ -0,0 +1,73 @@
// Copyright (c) 2014 Kohei Takahashi.
//
// 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)
//
// See http://www.boost.org for most recent version including documentation.
#include <boost/detail/lightweight_test.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <vector>
#include <string>
int main()
{
typedef TUPLE<
std::vector<int>::iterator,
std::vector<std::string>::iterator
> iterator_tuple;
std::vector<int> vi = boost::assign::list_of(42)(72);
std::vector<std::string> vs = boost::assign::list_of("kokoro")("pyonpyon");
{
boost::zip_iterator<iterator_tuple> i1(MAKE_TUPLE(vi.begin(), vs.begin()));
boost::zip_iterator<iterator_tuple> i2 = i1;
BOOST_TEST( i1 == i2);
BOOST_TEST( i1++ == i2);
BOOST_TEST( i1 == (i2 + 1));
BOOST_TEST((i1 - 1) == i2);
BOOST_TEST( i1-- == ++i2);
BOOST_TEST( i1 == --i2);
}
{
boost::zip_iterator<iterator_tuple> i1(MAKE_TUPLE(vi.begin(), vs.begin()));
boost::zip_iterator<iterator_tuple> i2 = i1 + 1;
BOOST_TEST( i1 != i2);
BOOST_TEST( i1++ != i2);
BOOST_TEST( i1 != (i2 + 1));
BOOST_TEST((i1 - 1) != i2);
BOOST_TEST( i1-- != ++i2);
BOOST_TEST( i1 != --i2);
}
{
boost::zip_iterator<iterator_tuple> i(MAKE_TUPLE(vi.begin(), vs.begin()));
BOOST_TEST(boost::fusion::at_c<0>(* i ) == 42);
BOOST_TEST(boost::fusion::at_c<1>(* i ) == "kokoro");
BOOST_TEST(boost::fusion::at_c<0>(*(i + 1)) == 72);
BOOST_TEST(boost::fusion::at_c<1>(*(i + 1)) == "pyonpyon");
}
{
boost::zip_iterator<iterator_tuple> i1(MAKE_TUPLE(vi.begin(), vs.begin()));
boost::zip_iterator<iterator_tuple> i2(MAKE_TUPLE(vi.end(), vs.end()));
BOOST_TEST((i2 - i1) == 2);
++i1;
BOOST_TEST((i2 - i1) == 1);
--i2;
BOOST_TEST((i2 - i1) == 0);
}
return boost::report_errors();
}

View File

@ -0,0 +1,857 @@
// (C) Copyright Dave Abrahams and Thomas Becker 2003. 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)
//
// File:
// =====
// zip_iterator_test_main.cpp
// Author:
// =======
// Thomas Becker
// Created:
// ========
// Jul 15, 2003
// Purpose:
// ========
// Test driver for zip_iterator.hpp
// Compilers Tested:
// =================
// Metrowerks Codewarrior Pro 7.2, 8.3
// gcc 2.95.3
// gcc 3.2
// Microsoft VC 6sp5 (test fails due to some compiler bug)
// Microsoft VC 7 (works)
// Microsoft VC 7.1
// Intel 5
// Intel 6
// Intel 7.1
// Intel 8
// Borland 5.5.1 (broken due to lack of support from Boost.Tuples)
/////////////////////////////////////////////////////////////////////////////
//
// Includes
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/iterator/zip_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp> // 2nd #include tests #include guard.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <string>
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/is_readable_iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp>
#include <stddef.h>
/// Tests for https://svn.boost.org/trac/boost/ticket/1517
int to_value(int const &v)
{
return v;
}
void category_test()
{
std::list<int> rng1;
std::string rng2;
boost::make_zip_iterator(
ZI_MAKE_TUPLE(
boost::make_transform_iterator(rng1.begin(), &to_value), // BidirectionalInput
rng2.begin() // RandomAccess
)
);
}
///
/////////////////////////////////////////////////////////////////////////////
//
// Das Main Funktion
//
/////////////////////////////////////////////////////////////////////////////
int main( void )
{
category_test();
std::cout << "\n"
<< "***********************************************\n"
<< "* *\n"
<< "* Test driver for boost::zip_iterator *\n"
<< "* Copyright Thomas Becker 2003 *\n"
<< "* *\n"
<< "***********************************************\n\n"
<< std::flush;
size_t num_successful_tests = 0;
size_t num_failed_tests = 0;
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator construction and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator construction and dereferencing: "
<< std::flush;
std::vector<double> vect1(3);
vect1[0] = 42.;
vect1[1] = 43.;
vect1[2] = 44.;
std::set<int> intset;
intset.insert(52);
intset.insert(53);
intset.insert(54);
//
typedef
boost::zip_iterator<
ZI_TUPLE<
std::set<int>::iterator
, std::vector<double>::iterator
>
> zit_mixed;
zit_mixed zip_it_mixed = zit_mixed(
ZI_MAKE_TUPLE(
intset.begin()
, vect1.begin()
)
);
ZI_TUPLE<int, double> val_tuple(
*zip_it_mixed);
ZI_TUPLE<const int&, double&> ref_tuple(
*zip_it_mixed);
double dblOldVal = ZI_TUPLE_GET(1)(ref_tuple);
ZI_TUPLE_GET(1)(ref_tuple) -= 41.;
if( 52 == ZI_TUPLE_GET(0)(val_tuple) &&
42. == ZI_TUPLE_GET(1)(val_tuple) &&
52 == ZI_TUPLE_GET(0)(ref_tuple) &&
1. == ZI_TUPLE_GET(1)(ref_tuple) &&
1. == *vect1.begin()
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
// Undo change to vect1
ZI_TUPLE_GET(1)(ref_tuple) = dblOldVal;
#if defined(ZI_USE_BOOST_TUPLE)
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator with 12 components
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterators with 12 components: "
<< std::flush;
// Declare 12 containers
//
std::list<int> li1;
li1.push_back(1);
std::set<int> se1;
se1.insert(2);
std::vector<int> ve1;
ve1.push_back(3);
//
std::list<int> li2;
li2.push_back(4);
std::set<int> se2;
se2.insert(5);
std::vector<int> ve2;
ve2.push_back(6);
//
std::list<int> li3;
li3.push_back(7);
std::set<int> se3;
se3.insert(8);
std::vector<int> ve3;
ve3.push_back(9);
//
std::list<int> li4;
li4.push_back(10);
std::set<int> se4;
se4.insert(11);
std::vector<int> ve4;
ve4.push_back(12);
// typedefs for cons lists of iterators.
typedef boost::tuples::cons<
std::set<int>::iterator,
ZI_TUPLE<
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::const_iterator
>::inherited
> cons_11_its_type;
//
typedef boost::tuples::cons<
std::list<int>::const_iterator,
cons_11_its_type
> cons_12_its_type;
// typedefs for cons lists for dereferencing the zip iterator
// made from the cons list above.
typedef boost::tuples::cons<
const int&,
ZI_TUPLE<
int&,
int&,
const int&,
int&,
int&,
const int&,
int&,
int&,
const int&,
const int&
>::inherited
> cons_11_refs_type;
//
typedef boost::tuples::cons<
const int&,
cons_11_refs_type
> cons_12_refs_type;
// typedef for zip iterator with 12 elements
typedef boost::zip_iterator<cons_12_its_type> zip_it_12_type;
// Declare a 12-element zip iterator.
zip_it_12_type zip_it_12(
cons_12_its_type(
li1.begin(),
cons_11_its_type(
se1.begin(),
ZI_MAKE_TUPLE(
ve1.begin(),
li2.begin(),
se2.begin(),
ve2.begin(),
li3.begin(),
se3.begin(),
ve3.begin(),
li4.begin(),
se4.begin(),
ve4.begin()
)
)
)
);
// Dereference, mess with the result a little.
cons_12_refs_type zip_it_12_dereferenced(*zip_it_12);
ZI_TUPLE_GET(9)(zip_it_12_dereferenced) = 42;
// Make a copy and move it a little to force some instantiations.
zip_it_12_type zip_it_12_copy(zip_it_12);
++zip_it_12_copy;
if( ZI_TUPLE_GET(11)(zip_it_12.get_iterator_tuple()) == ve4.begin() &&
ZI_TUPLE_GET(11)(zip_it_12_copy.get_iterator_tuple()) == ve4.end() &&
1 == ZI_TUPLE_GET(0)(zip_it_12_dereferenced) &&
12 == ZI_TUPLE_GET(11)(zip_it_12_dereferenced) &&
42 == *(li4.begin())
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator incrementing and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator ++ and *: "
<< std::flush;
std::vector<double> vect2(3);
vect2[0] = 2.2;
vect2[1] = 3.3;
vect2[2] = 4.4;
boost::zip_iterator<
ZI_TUPLE<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_begin(
ZI_MAKE_TUPLE(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
ZI_TUPLE<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_run(
ZI_MAKE_TUPLE(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
ZI_TUPLE<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_end(
ZI_MAKE_TUPLE(
vect1.end(),
vect2.end()
)
);
if( zip_it_run == zip_it_begin &&
42. == ZI_TUPLE_GET(0)(*zip_it_run) &&
2.2 == ZI_TUPLE_GET(1)(*zip_it_run) &&
43. == ZI_TUPLE_GET(0)(*(++zip_it_run)) &&
3.3 == ZI_TUPLE_GET(1)(*zip_it_run) &&
44. == ZI_TUPLE_GET(0)(*(++zip_it_run)) &&
4.4 == ZI_TUPLE_GET(1)(*zip_it_run) &&
zip_it_end == ++zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator decrementing and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator -- and *: "
<< std::flush;
if( zip_it_run == zip_it_end &&
zip_it_end == zip_it_run-- &&
44. == ZI_TUPLE_GET(0)(*zip_it_run) &&
4.4 == ZI_TUPLE_GET(1)(*zip_it_run) &&
43. == ZI_TUPLE_GET(0)(*(--zip_it_run)) &&
3.3 == ZI_TUPLE_GET(1)(*zip_it_run) &&
42. == ZI_TUPLE_GET(0)(*(--zip_it_run)) &&
2.2 == ZI_TUPLE_GET(1)(*zip_it_run) &&
zip_it_begin == zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator copy construction and equality
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator copy construction and equality: "
<< std::flush;
boost::zip_iterator<
ZI_TUPLE<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> zip_it_run_copy(zip_it_run);
if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator inequality
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator inequality: "
<< std::flush;
if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator less than
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator less than: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run + 1
//
if( zip_it_run < zip_it_run_copy &&
!( zip_it_run < --zip_it_run_copy) &&
zip_it_run == zip_it_run_copy
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator less than or equal
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "zip iterator less than or equal: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run
//
++zip_it_run;
zip_it_run_copy += 2;
if( zip_it_run <= zip_it_run_copy &&
zip_it_run <= --zip_it_run_copy &&
!( zip_it_run <= --zip_it_run_copy) &&
zip_it_run <= zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator greater than
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator greater than: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run - 1
//
if( zip_it_run > zip_it_run_copy &&
!( zip_it_run > ++zip_it_run_copy) &&
zip_it_run == zip_it_run_copy
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator greater than or equal
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator greater than or equal: "
<< std::flush;
++zip_it_run;
// Note: zip_it_run == zip_it_run_copy + 1
//
if( zip_it_run >= zip_it_run_copy &&
--zip_it_run >= zip_it_run_copy &&
! (zip_it_run >= ++zip_it_run_copy)
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator + int
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator + int: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy - 1
//
zip_it_run = zip_it_run + 2;
++zip_it_run_copy;
if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator - int
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator - int: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy, and both are at end position
//
zip_it_run = zip_it_run - 2;
--zip_it_run_copy;
--zip_it_run_copy;
if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator +=
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator +=: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy, and both are at begin + 1
//
zip_it_run += 2;
if( zip_it_run == zip_it_begin + 3 )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator -=
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator -=: "
<< std::flush;
// Note: zip_it_run is at end position, zip_it_run_copy is at
// begin plus one.
//
zip_it_run -= 2;
if( zip_it_run == zip_it_run_copy )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator getting member iterators
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator member iterators: "
<< std::flush;
// Note: zip_it_run and zip_it_run_copy are both at
// begin plus one.
//
if( ZI_TUPLE_GET(0)(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 &&
ZI_TUPLE_GET(1)(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Making zip iterators
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Making zip iterators: "
<< std::flush;
std::vector<ZI_TUPLE<double, double> >
vect_of_tuples(3);
std::copy(
boost::make_zip_iterator(
ZI_MAKE_TUPLE(
vect1.begin(),
vect2.begin()
)
),
boost::make_zip_iterator(
ZI_MAKE_TUPLE(
vect1.end(),
vect2.end()
)
),
vect_of_tuples.begin()
);
if( 42. == ZI_TUPLE_GET(0)(*vect_of_tuples.begin()) &&
2.2 == ZI_TUPLE_GET(1)(*vect_of_tuples.begin()) &&
43. == ZI_TUPLE_GET(0)(*(vect_of_tuples.begin() + 1)) &&
3.3 == ZI_TUPLE_GET(1)(*(vect_of_tuples.begin() + 1)) &&
44. == ZI_TUPLE_GET(0)(*(vect_of_tuples.begin() + 2)) &&
4.4 == ZI_TUPLE_GET(1)(*(vect_of_tuples.begin() + 2))
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator non-const --> const conversion
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator non-const to const conversion: "
<< std::flush;
boost::zip_iterator<
ZI_TUPLE<
std::set<int>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_const(
ZI_MAKE_TUPLE(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
ZI_TUPLE<
std::set<int>::iterator,
std::vector<double>::const_iterator
>
>
zip_it_half_const(
ZI_MAKE_TUPLE(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
ZI_TUPLE<
std::set<int>::iterator,
std::vector<double>::iterator
>
>
zip_it_non_const(
ZI_MAKE_TUPLE(
intset.begin(),
vect2.begin()
)
);
zip_it_half_const = ++zip_it_non_const;
zip_it_const = zip_it_half_const;
++zip_it_const;
// zip_it_non_const = ++zip_it_const; // Error: can't convert from const to non-const
if( 54 == ZI_TUPLE_GET(0)(*zip_it_const) &&
4.4 == ZI_TUPLE_GET(1)(*zip_it_const) &&
53 == ZI_TUPLE_GET(0)(*zip_it_half_const) &&
3.3 == ZI_TUPLE_GET(1)(*zip_it_half_const)
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
#if defined(ZI_USE_BOOST_TUPLE)
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator categories
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator categories: "
<< std::flush;
// The big iterator of the previous test has vector, list, and set iterators.
// Therefore, it must be bidirectional, but not random access.
bool bBigItIsBidirectionalIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::bidirectional_traversal_tag
>::value;
bool bBigItIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::random_access_traversal_tag
>::value;
// A combining iterator with all vector iterators must have random access
// traversal.
//
typedef boost::zip_iterator<
ZI_TUPLE<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> all_vects_type;
bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<all_vects_type>::type
, boost::random_access_traversal_tag
>::value;
// The big test.
if( bBigItIsBidirectionalIterator &&
! bBigItIsRandomAccessIterator &&
bAllVectsIsRandomAccessIterator
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests;
std::cout << "not OK" << std::endl;
}
#endif
// Done
//
std::cout << "\nTest Result:"
<< "\n============"
<< "\nNumber of successful tests: " << static_cast<unsigned int>(num_successful_tests)
<< "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
<< std::endl;
return num_failed_tests;
}

View File

@ -8,6 +8,7 @@
#include <boost/iterator/new_iterator_tests.hpp>
#include <boost/call_traits.hpp>
#include <boost/polymorphic_cast.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
@ -49,14 +50,14 @@ class counter_iterator
struct proxy
{
proxy(int& x) : state(x) {}
operator int const&() const
{
return state;
}
int& operator=(int x) { state = x; return state; }
int& state;
};
@ -128,6 +129,61 @@ template <class T, class U>
void same_type(U const&)
{ BOOST_MPL_ASSERT((boost::is_same<T,U>)); }
template <class I, class A>
struct abstract_iterator
: boost::iterator_facade<
abstract_iterator<I, A>
, A &
// In order to be value type as a reference, traversal category has
// to satisfy least forward traversal.
, boost::forward_traversal_tag
, A &
>
{
abstract_iterator(I iter) : iter(iter) {}
void increment()
{ ++iter; }
A & dereference() const
{ return *iter; }
bool equal(abstract_iterator const& y) const
{ return iter == y.iter; }
I iter;
};
struct base
{
virtual void assign(const base &) = 0;
virtual bool equal(const base &) const = 0;
};
struct derived : base
{
derived(int state) : state(state) { }
derived(const derived &d) : state(d.state) { }
derived(const base &b) { derived::assign(b); }
virtual void assign(const base &b)
{
state = boost::polymorphic_cast<const derived *>(&b)->state;
}
virtual bool equal(const base &b) const
{
return state == boost::polymorphic_cast<const derived *>(&b)->state;
}
int state;
};
inline bool operator==(const base &lhs, const base &rhs)
{
return lhs.equal(rhs);
}
int main()
{
{
@ -162,5 +218,10 @@ int main()
BOOST_TEST(i.m_x == 2);
}
{
derived d(1);
boost::readable_iterator_test(abstract_iterator<derived *, base>(&d), derived(1));
}
return boost::report_errors();
}

View File

@ -1,850 +1,8 @@
// (C) Copyright Dave Abrahams and Thomas Becker 2003. 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)
//
// File:
// =====
// zip_iterator_test_main.cpp
// Author:
// =======
// Thomas Becker
// Created:
// ========
// Jul 15, 2003
// Purpose:
// ========
// Test driver for zip_iterator.hpp
// Compilers Tested:
// =================
// Metrowerks Codewarrior Pro 7.2, 8.3
// gcc 2.95.3
// gcc 3.2
// Microsoft VC 6sp5 (test fails due to some compiler bug)
// Microsoft VC 7 (works)
// Microsoft VC 7.1
// Intel 5
// Intel 6
// Intel 7.1
// Intel 8
// Borland 5.5.1 (broken due to lack of support from Boost.Tuples)
/////////////////////////////////////////////////////////////////////////////
//
// Includes
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/iterator/zip_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp> // 2nd #include tests #include guard.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <string>
#include <functional>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/is_readable_iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp>
#include <stddef.h>
#define ZI_TUPLE boost::tuples::tuple
#define ZI_MAKE_TUPLE boost::make_tuple
#define ZI_TUPLE_GET(n) boost::tuples::get<n>
#define ZI_USE_BOOST_TUPLE
/// Tests for https://svn.boost.org/trac/boost/ticket/1517
int to_value(int const &v)
{
return v;
}
void category_test()
{
std::list<int> rng1;
std::string rng2;
boost::make_zip_iterator(
boost::make_tuple(
boost::make_transform_iterator(rng1.begin(), &to_value), // BidirectionalInput
rng2.begin() // RandomAccess
)
);
}
///
/////////////////////////////////////////////////////////////////////////////
//
// Das Main Funktion
//
/////////////////////////////////////////////////////////////////////////////
int main( void )
{
category_test();
std::cout << "\n"
<< "***********************************************\n"
<< "* *\n"
<< "* Test driver for boost::zip_iterator *\n"
<< "* Copyright Thomas Becker 2003 *\n"
<< "* *\n"
<< "***********************************************\n\n"
<< std::flush;
size_t num_successful_tests = 0;
size_t num_failed_tests = 0;
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator construction and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator construction and dereferencing: "
<< std::flush;
std::vector<double> vect1(3);
vect1[0] = 42.;
vect1[1] = 43.;
vect1[2] = 44.;
std::set<int> intset;
intset.insert(52);
intset.insert(53);
intset.insert(54);
//
typedef
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator
, std::vector<double>::iterator
>
> zit_mixed;
zit_mixed zip_it_mixed = zit_mixed(
boost::make_tuple(
intset.begin()
, vect1.begin()
)
);
boost::tuples::tuple<int, double> val_tuple(
*zip_it_mixed);
boost::tuples::tuple<const int&, double&> ref_tuple(
*zip_it_mixed);
double dblOldVal = boost::tuples::get<1>(ref_tuple);
boost::tuples::get<1>(ref_tuple) -= 41.;
if( 52 == boost::tuples::get<0>(val_tuple) &&
42. == boost::tuples::get<1>(val_tuple) &&
52 == boost::tuples::get<0>(ref_tuple) &&
1. == boost::tuples::get<1>(ref_tuple) &&
1. == *vect1.begin()
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
// Undo change to vect1
boost::tuples::get<1>(ref_tuple) = dblOldVal;
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator with 12 components
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterators with 12 components: "
<< std::flush;
// Declare 12 containers
//
std::list<int> li1;
li1.push_back(1);
std::set<int> se1;
se1.insert(2);
std::vector<int> ve1;
ve1.push_back(3);
//
std::list<int> li2;
li2.push_back(4);
std::set<int> se2;
se2.insert(5);
std::vector<int> ve2;
ve2.push_back(6);
//
std::list<int> li3;
li3.push_back(7);
std::set<int> se3;
se3.insert(8);
std::vector<int> ve3;
ve3.push_back(9);
//
std::list<int> li4;
li4.push_back(10);
std::set<int> se4;
se4.insert(11);
std::vector<int> ve4;
ve4.push_back(12);
// typedefs for cons lists of iterators.
typedef boost::tuples::cons<
std::set<int>::iterator,
boost::tuples::tuple<
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::const_iterator
>::inherited
> cons_11_its_type;
//
typedef boost::tuples::cons<
std::list<int>::const_iterator,
cons_11_its_type
> cons_12_its_type;
// typedefs for cons lists for dereferencing the zip iterator
// made from the cons list above.
typedef boost::tuples::cons<
const int&,
boost::tuples::tuple<
int&,
int&,
const int&,
int&,
int&,
const int&,
int&,
int&,
const int&,
const int&
>::inherited
> cons_11_refs_type;
//
typedef boost::tuples::cons<
const int&,
cons_11_refs_type
> cons_12_refs_type;
// typedef for zip iterator with 12 elements
typedef boost::zip_iterator<cons_12_its_type> zip_it_12_type;
// Declare a 12-element zip iterator.
zip_it_12_type zip_it_12(
cons_12_its_type(
li1.begin(),
cons_11_its_type(
se1.begin(),
boost::make_tuple(
ve1.begin(),
li2.begin(),
se2.begin(),
ve2.begin(),
li3.begin(),
se3.begin(),
ve3.begin(),
li4.begin(),
se4.begin(),
ve4.begin()
)
)
)
);
// Dereference, mess with the result a little.
cons_12_refs_type zip_it_12_dereferenced(*zip_it_12);
boost::tuples::get<9>(zip_it_12_dereferenced) = 42;
// Make a copy and move it a little to force some instantiations.
zip_it_12_type zip_it_12_copy(zip_it_12);
++zip_it_12_copy;
if( boost::tuples::get<11>(zip_it_12.get_iterator_tuple()) == ve4.begin() &&
boost::tuples::get<11>(zip_it_12_copy.get_iterator_tuple()) == ve4.end() &&
1 == boost::tuples::get<0>(zip_it_12_dereferenced) &&
12 == boost::tuples::get<11>(zip_it_12_dereferenced) &&
42 == *(li4.begin())
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator incrementing and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator ++ and *: "
<< std::flush;
std::vector<double> vect2(3);
vect2[0] = 2.2;
vect2[1] = 3.3;
vect2[2] = 4.4;
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_begin(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_run(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_end(
boost::make_tuple(
vect1.end(),
vect2.end()
)
);
if( zip_it_run == zip_it_begin &&
42. == boost::tuples::get<0>(*zip_it_run) &&
2.2 == boost::tuples::get<1>(*zip_it_run) &&
43. == boost::tuples::get<0>(*(++zip_it_run)) &&
3.3 == boost::tuples::get<1>(*zip_it_run) &&
44. == boost::tuples::get<0>(*(++zip_it_run)) &&
4.4 == boost::tuples::get<1>(*zip_it_run) &&
zip_it_end == ++zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator decrementing and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator -- and *: "
<< std::flush;
if( zip_it_run == zip_it_end &&
zip_it_end == zip_it_run-- &&
44. == boost::tuples::get<0>(*zip_it_run) &&
4.4 == boost::tuples::get<1>(*zip_it_run) &&
43. == boost::tuples::get<0>(*(--zip_it_run)) &&
3.3 == boost::tuples::get<1>(*zip_it_run) &&
42. == boost::tuples::get<0>(*(--zip_it_run)) &&
2.2 == boost::tuples::get<1>(*zip_it_run) &&
zip_it_begin == zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator copy construction and equality
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator copy construction and equality: "
<< std::flush;
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> zip_it_run_copy(zip_it_run);
if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator inequality
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator inequality: "
<< std::flush;
if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator less than
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator less than: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run + 1
//
if( zip_it_run < zip_it_run_copy &&
!( zip_it_run < --zip_it_run_copy) &&
zip_it_run == zip_it_run_copy
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator less than or equal
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "zip iterator less than or equal: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run
//
++zip_it_run;
zip_it_run_copy += 2;
if( zip_it_run <= zip_it_run_copy &&
zip_it_run <= --zip_it_run_copy &&
!( zip_it_run <= --zip_it_run_copy) &&
zip_it_run <= zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator greater than
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator greater than: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run - 1
//
if( zip_it_run > zip_it_run_copy &&
!( zip_it_run > ++zip_it_run_copy) &&
zip_it_run == zip_it_run_copy
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator greater than or equal
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator greater than or equal: "
<< std::flush;
++zip_it_run;
// Note: zip_it_run == zip_it_run_copy + 1
//
if( zip_it_run >= zip_it_run_copy &&
--zip_it_run >= zip_it_run_copy &&
! (zip_it_run >= ++zip_it_run_copy)
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator + int
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator + int: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy - 1
//
zip_it_run = zip_it_run + 2;
++zip_it_run_copy;
if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator - int
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator - int: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy, and both are at end position
//
zip_it_run = zip_it_run - 2;
--zip_it_run_copy;
--zip_it_run_copy;
if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator +=
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator +=: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy, and both are at begin + 1
//
zip_it_run += 2;
if( zip_it_run == zip_it_begin + 3 )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator -=
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator -=: "
<< std::flush;
// Note: zip_it_run is at end position, zip_it_run_copy is at
// begin plus one.
//
zip_it_run -= 2;
if( zip_it_run == zip_it_run_copy )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator getting member iterators
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator member iterators: "
<< std::flush;
// Note: zip_it_run and zip_it_run_copy are both at
// begin plus one.
//
if( boost::tuples::get<0>(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 &&
boost::tuples::get<1>(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Making zip iterators
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Making zip iterators: "
<< std::flush;
std::vector<boost::tuples::tuple<double, double> >
vect_of_tuples(3);
std::copy(
boost::make_zip_iterator(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
),
boost::make_zip_iterator(
boost::make_tuple(
vect1.end(),
vect2.end()
)
),
vect_of_tuples.begin()
);
if( 42. == boost::tuples::get<0>(*vect_of_tuples.begin()) &&
2.2 == boost::tuples::get<1>(*vect_of_tuples.begin()) &&
43. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 1)) &&
3.3 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 1)) &&
44. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 2)) &&
4.4 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 2))
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator non-const --> const conversion
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator non-const to const conversion: "
<< std::flush;
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator,
std::vector<double>::const_iterator
>
>
zip_it_half_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator,
std::vector<double>::iterator
>
>
zip_it_non_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
zip_it_half_const = ++zip_it_non_const;
zip_it_const = zip_it_half_const;
++zip_it_const;
// zip_it_non_const = ++zip_it_const; // Error: can't convert from const to non-const
if( 54 == boost::tuples::get<0>(*zip_it_const) &&
4.4 == boost::tuples::get<1>(*zip_it_const) &&
53 == boost::tuples::get<0>(*zip_it_half_const) &&
3.3 == boost::tuples::get<1>(*zip_it_half_const)
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator categories
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator categories: "
<< std::flush;
// The big iterator of the previous test has vector, list, and set iterators.
// Therefore, it must be bidirectional, but not random access.
bool bBigItIsBidirectionalIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::bidirectional_traversal_tag
>::value;
bool bBigItIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::random_access_traversal_tag
>::value;
// A combining iterator with all vector iterators must have random access
// traversal.
//
typedef boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> all_vects_type;
bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<all_vects_type>::type
, boost::random_access_traversal_tag
>::value;
// The big test.
if( bBigItIsBidirectionalIterator &&
! bBigItIsRandomAccessIterator &&
bAllVectsIsRandomAccessIterator
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
// Done
//
std::cout << "\nTest Result:"
<< "\n============"
<< "\nNumber of successful tests: " << static_cast<unsigned int>(num_successful_tests)
<< "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
<< std::endl;
return num_failed_tests;
}
#include "detail/zip_iterator_test_original.ipp"

View File

@ -0,0 +1,9 @@
#include <boost/fusion/include/deque.hpp>
#include <boost/fusion/include/make_deque.hpp>
#include <boost/fusion/sequence/intrinsic/at_c.hpp>
#define ZI_TUPLE boost::fusion::deque
#define ZI_MAKE_TUPLE boost::fusion::make_deque
#define ZI_TUPLE_GET(n) boost::fusion::at_c<n>
#include "detail/zip_iterator_test_original.ipp"

View File

@ -0,0 +1,11 @@
#include <boost/config.hpp>
#include <boost/fusion/include/list.hpp>
#include <boost/fusion/include/make_list.hpp>
#include <boost/fusion/sequence/intrinsic/at_c.hpp>
#define ZI_TUPLE boost::fusion::list
#define ZI_MAKE_TUPLE boost::fusion::make_list
#define ZI_TUPLE_GET(n) boost::fusion::at_c<n>
#include "detail/zip_iterator_test_original.ipp"

View File

@ -0,0 +1,11 @@
#include <boost/config.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/sequence/intrinsic/at_c.hpp>
#define ZI_TUPLE boost::fusion::vector
#define ZI_MAKE_TUPLE boost::fusion::make_vector
#define ZI_TUPLE_GET(n) boost::fusion::at_c<n>
#include "detail/zip_iterator_test_original.ipp"

View File

@ -0,0 +1,21 @@
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
#include <tuple>
#include <boost/fusion/adapted/std_tuple.hpp>
#define ZI_TUPLE std::tuple
#define ZI_MAKE_TUPLE std::make_tuple
#define ZI_TUPLE_GET(n) std::get<n>
#include "detail/zip_iterator_test_original.ipp"
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,15 @@
// Copyright (c) 2014 Kohei Takahashi.
//
// 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)
//
// See http://www.boost.org for most recent version including documentation.
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/make_vector.hpp>
#define TUPLE boost::fusion::vector
#define MAKE_TUPLE boost::fusion::make_vector
#include "detail/zip_iterator_test.ipp"

View File

@ -0,0 +1,16 @@
// Copyright (c) 2014 Kohei Takahashi.
//
// 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)
//
// See http://www.boost.org for most recent version including documentation.
#include <utility>
#include <boost/fusion/adapted/std_pair.hpp>
#define TUPLE std::pair
#define MAKE_TUPLE std::make_pair
#include "detail/zip_iterator_test.ipp"

View File

@ -0,0 +1,29 @@
// Copyright (c) 2014 Kohei Takahashi.
//
// 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)
//
// See http://www.boost.org for most recent version including documentation.
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <tuple>
#include <boost/fusion/adapted/std_tuple.hpp>
#define TUPLE std::tuple
#define MAKE_TUPLE std::make_tuple
#include "detail/zip_iterator_test.ipp"
#else
int main()
{
return 0;
}
#endif