mirror of
https://github.com/boostorg/iterator.git
synced 2025-06-27 21:11:02 +02:00
Compare commits
209 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
6ca935d9fe | |||
dea89aa823 | |||
ce5d2ec4b4 | |||
640379ac34 | |||
7cbe926f29 | |||
5113e4fbec | |||
66183e43f5 | |||
4247559960 | |||
c7c6448bd5 | |||
218778bb94 | |||
4b4de44736 | |||
8deb1c20fb | |||
20e6d71755 | |||
52f72c2115 | |||
6b2da49430 | |||
f46f7f8091 | |||
22670777b8 | |||
6270de1db0 | |||
6e06e4f89e | |||
eb73b8e0e2 | |||
7ffe2601a9 | |||
62b70f57a9 | |||
cd37eb3bfb | |||
bda5890235 | |||
d51c5ebf07 | |||
6f90b8b161 | |||
6ec791e3b9 | |||
20f188d971 | |||
7273be17c0 | |||
77a89a0b89 | |||
4968b50fc2 | |||
cbeb7f0632 | |||
abf8390020 | |||
2c89e2b15a | |||
3f49409843 | |||
abafc5d1be | |||
2b7ed5f7a8 | |||
f801c39a59 | |||
bb7ac6bd84 | |||
f325582c40 | |||
36feca8a52 | |||
a5179f6dfc | |||
f98f3497b8 | |||
76af84c0e7 | |||
0f42b93c3b | |||
19977c757f | |||
508696a169 | |||
3ab9da6a99 | |||
bd3312cdf2 | |||
87f93ec521 | |||
afa92675a2 | |||
ed8c60c20b | |||
3fe0d4b532 | |||
8a51271e3b | |||
52c0d22cff | |||
e4447b8e83 | |||
42e873e10c | |||
57a40c8cd2 | |||
a982c42303 | |||
9db269bb5b | |||
e5eaaf6a55 | |||
2225787093 | |||
f19c1c4059 | |||
b0aef5a66d | |||
dfc43d81cf | |||
eda969d7b5 | |||
4c8415a99f | |||
1d6f36e35d | |||
04301ac6e9 | |||
a1ec9da737 | |||
e2a47bdbe5 | |||
2b1fc22b61 | |||
273ec4b975 | |||
4716891117 | |||
80d9e8e4c1 | |||
53eb5346de | |||
e28ca345ea | |||
92d461cda1 | |||
8dace06f04 | |||
ef0bff57d3 | |||
5bacd289b6 | |||
77c1698c6e | |||
2c302ee549 | |||
a586f20d19 | |||
34c159dd8d | |||
b22a3adc02 | |||
4a24e0f401 | |||
3844edc4bf | |||
fdd1601ba4 | |||
e9b33b336c | |||
2574365b5c | |||
12b9366f33 | |||
4772bb099e | |||
2be5179020 | |||
8cb49713b4 | |||
bd666dc0e9 | |||
57251d58cc | |||
ebcb4d861a | |||
15a7a839f9 | |||
76a307d31e | |||
37aee7c13b | |||
50a502bb81 | |||
8a4839354e | |||
4da7371246 | |||
e162a75e53 | |||
e60df6ad92 | |||
4c2b3a9d2c | |||
75023a1dd3 | |||
79370a6dfb | |||
4566798afc | |||
3fd1c4bc5d | |||
2d6f48d5ab | |||
d1c7594344 | |||
ac327f51e9 | |||
4e18b11263 | |||
81e3df2b36 | |||
ac05307515 | |||
552a1e6785 | |||
134b8b51aa | |||
efecfd17b9 | |||
799158841e | |||
582ebfd054 | |||
42e4db1539 | |||
d7023154a3 | |||
9582b2223c | |||
d7908fb81f | |||
e48cdcb94f | |||
0846ad5fd0 | |||
84663ff2e2 | |||
6de1934420 | |||
a110b9fd27 | |||
eb06c122d1 | |||
cbbe851adb | |||
f6cc2e520f | |||
4e29b5aa29 | |||
d924f56ad8 | |||
f27fd095f7 | |||
d22edf735a | |||
af8dd117d5 | |||
149d07cda0 | |||
e9d9bdbb10 | |||
8d8f828da5 | |||
fc15f5f710 | |||
ef66d28b19 | |||
0c8d74863f | |||
1c73f1f2ae | |||
ee20a630dd | |||
c2472221ef | |||
bf45977491 | |||
1988994bd3 | |||
5482763a93 | |||
2c2a3eab21 | |||
dca20fae75 | |||
e3aaf2cc91 | |||
ea4c7c7dd9 | |||
fd6ba58d5e | |||
268e70faa1 | |||
170b44763d | |||
b2701f9f78 | |||
ad4c5ab089 | |||
c585adde71 | |||
c5f24d0d72 | |||
dbb99b1cf3 | |||
be44a4714b | |||
e9f24023d4 | |||
51616fa845 | |||
d7884b5613 | |||
15b5b66776 | |||
6f90982a45 | |||
bfda34e9e0 | |||
5bfc03ed4a | |||
490bee3a06 | |||
8174963a45 | |||
86e183c75e | |||
a94c9d0db2 | |||
8a73dcd052 | |||
8496571204 | |||
bafe0703a6 | |||
b05b38810c | |||
edf17ba001 | |||
ee9f140fae | |||
762e603013 | |||
6eeeb23332 | |||
07482538ed | |||
d17e8dae9b | |||
5e1bc30db9 | |||
e8389d5f49 | |||
332f18cf9f | |||
7aea7b7881 | |||
3e6796ab91 | |||
893b5c0e25 | |||
41c334d718 | |||
05336f45c4 | |||
90299982a6 | |||
93b54c15c8 | |||
25f9acabac | |||
bb2ffadade | |||
b6aa32721f | |||
8f41e88f85 | |||
58b56fbabb | |||
9a4b0b576d | |||
c948483ec1 | |||
a31a89ae7d | |||
b8ccd48fa3 | |||
cf1d6a30af | |||
7fa5da6778 | |||
34a9d4e702 | |||
42710d0967 | |||
487acf8c1c |
210
include/boost/iterator/counting_iterator.hpp
Normal file
210
include/boost/iterator/counting_iterator.hpp
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef COUNTING_ITERATOR_DWA200348_HPP
|
||||||
|
# define COUNTING_ITERATOR_DWA200348_HPP
|
||||||
|
|
||||||
|
# include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
# include <boost/detail/numeric_traits.hpp>
|
||||||
|
# include <boost/mpl/bool.hpp>
|
||||||
|
# include <boost/mpl/if.hpp>
|
||||||
|
# include <boost/mpl/identity.hpp>
|
||||||
|
# include <boost/mpl/apply_if.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Incrementable
|
||||||
|
, class CategoryOrTraversal
|
||||||
|
, class Difference
|
||||||
|
>
|
||||||
|
class counting_iterator;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// Try to detect numeric types at compile time in ways compatible
|
||||||
|
// with the limitations of the compiler and library.
|
||||||
|
template <class T>
|
||||||
|
struct is_numeric_impl
|
||||||
|
{
|
||||||
|
// For a while, this wasn't true, but we rely on it below. This is a regression assert.
|
||||||
|
BOOST_STATIC_ASSERT(::boost::is_integral<char>::value);
|
||||||
|
|
||||||
|
# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||||
|
|
||||||
|
# if defined(BOOST_HAS_LONG_LONG)
|
||||||
|
BOOST_STATIC_CONSTANT(
|
||||||
|
bool, value = (
|
||||||
|
std::numeric_limits<T>::is_specialized
|
||||||
|
| boost::is_same<T,long long>::value
|
||||||
|
| boost::is_same<T,unsigned long long>::value
|
||||||
|
));
|
||||||
|
# else
|
||||||
|
BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<T>::is_specialized);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
# if !defined(__BORLANDC__)
|
||||||
|
BOOST_STATIC_CONSTANT(
|
||||||
|
bool, value = (
|
||||||
|
boost::is_convertible<int,T>::value
|
||||||
|
&& boost::is_convertible<T,int>::value
|
||||||
|
));
|
||||||
|
# else
|
||||||
|
BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic<T>::value);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_numeric
|
||||||
|
: mpl::bool_<(::boost::detail::is_numeric_impl<T>::value)>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct numeric_difference
|
||||||
|
{
|
||||||
|
typedef typename boost::detail::numeric_traits<T>::difference_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(is_numeric<int>::value);
|
||||||
|
|
||||||
|
template <class Incrementable, class CategoryOrTraversal, class Difference>
|
||||||
|
struct counting_iterator_base
|
||||||
|
{
|
||||||
|
typedef typename detail::ia_dflt_help<
|
||||||
|
CategoryOrTraversal
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_numeric<Incrementable>
|
||||||
|
, mpl::identity<random_access_traversal_tag>
|
||||||
|
, iterator_traversal<Incrementable>
|
||||||
|
>
|
||||||
|
>::type traversal;
|
||||||
|
|
||||||
|
typedef typename detail::ia_dflt_help<
|
||||||
|
Difference
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_numeric<Incrementable>
|
||||||
|
, numeric_difference<Incrementable>
|
||||||
|
, iterator_difference<Incrementable>
|
||||||
|
>
|
||||||
|
>::type difference;
|
||||||
|
|
||||||
|
typedef iterator_adaptor<
|
||||||
|
counting_iterator<Incrementable, CategoryOrTraversal, Difference> // self
|
||||||
|
, Incrementable // Base
|
||||||
|
, Incrementable // Value
|
||||||
|
# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||||
|
const // MSVC won't strip this. Instead we enable Thomas'
|
||||||
|
// criterion (see boost/iterator/detail/facade_iterator_category.hpp)
|
||||||
|
# endif
|
||||||
|
, traversal
|
||||||
|
, Incrementable const& // reference
|
||||||
|
, difference
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Template class distance_policy_select -- choose a policy for computing the
|
||||||
|
// distance between counting_iterators at compile-time based on whether or not
|
||||||
|
// the iterator wraps an integer or an iterator, using "poor man's partial
|
||||||
|
// specialization".
|
||||||
|
|
||||||
|
template <bool is_integer> struct distance_policy_select;
|
||||||
|
|
||||||
|
// A policy for wrapped iterators
|
||||||
|
template <class Difference, class Incrementable1, class Incrementable2>
|
||||||
|
struct iterator_distance
|
||||||
|
{
|
||||||
|
static Difference distance(Incrementable1 x, Incrementable2 y)
|
||||||
|
{
|
||||||
|
return boost::detail::distance(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A policy for wrapped numbers
|
||||||
|
template <class Difference, class Incrementable1, class Incrementable2>
|
||||||
|
struct number_distance
|
||||||
|
{
|
||||||
|
static Difference distance(Incrementable1 x, Incrementable2 y)
|
||||||
|
{
|
||||||
|
return numeric_distance(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Incrementable
|
||||||
|
, class CategoryOrTraversal = use_default
|
||||||
|
, class Difference = use_default
|
||||||
|
>
|
||||||
|
class counting_iterator
|
||||||
|
: public detail::counting_iterator_base<
|
||||||
|
Incrementable, CategoryOrTraversal, Difference
|
||||||
|
>::type
|
||||||
|
{
|
||||||
|
typedef typename detail::counting_iterator_base<
|
||||||
|
Incrementable, CategoryOrTraversal, Difference
|
||||||
|
>::type super_t;
|
||||||
|
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename super_t::difference_type difference_type;
|
||||||
|
|
||||||
|
counting_iterator() { }
|
||||||
|
|
||||||
|
counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {}
|
||||||
|
|
||||||
|
counting_iterator(Incrementable x)
|
||||||
|
: super_t(x)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
# if 0
|
||||||
|
template<class OtherIncrementable>
|
||||||
|
counting_iterator(
|
||||||
|
counting_iterator<OtherIncrementable> const& t
|
||||||
|
, typename enable_if_convertible<OtherIncrementable, Incrementable>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(t.base())
|
||||||
|
{}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typename super_t::reference dereference() const
|
||||||
|
{
|
||||||
|
return this->base_reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class OtherIncrementable>
|
||||||
|
difference_type
|
||||||
|
distance_to(counting_iterator<OtherIncrementable> const& y) const
|
||||||
|
{
|
||||||
|
typedef typename mpl::if_<
|
||||||
|
detail::is_numeric<Incrementable>
|
||||||
|
, detail::number_distance<difference_type, Incrementable, OtherIncrementable>
|
||||||
|
, detail::iterator_distance<difference_type, Incrementable, OtherIncrementable>
|
||||||
|
>::type d;
|
||||||
|
|
||||||
|
return d::distance(this->base(), y.base());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Manufacture a counting iterator for an arbitrary incrementable type
|
||||||
|
template <class Incrementable>
|
||||||
|
inline counting_iterator<Incrementable>
|
||||||
|
make_counting_iterator(Incrementable x)
|
||||||
|
{
|
||||||
|
typedef counting_iterator<Incrementable> result_t;
|
||||||
|
return result_t(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace boost::iterator
|
||||||
|
|
||||||
|
#endif // COUNTING_ITERATOR_DWA200348_HPP
|
19
include/boost/iterator/detail/any_conversion_eater.hpp
Executable file
19
include/boost/iterator/detail/any_conversion_eater.hpp
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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 ANY_CONVERSION_EATER_DWA20031117_HPP
|
||||||
|
# define ANY_CONVERSION_EATER_DWA20031117_HPP
|
||||||
|
|
||||||
|
namespace boost { namespace detail {
|
||||||
|
|
||||||
|
// This type can be used in traits to "eat" up the one user-defined
|
||||||
|
// implicit conversion allowed.
|
||||||
|
struct any_conversion_eater
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
any_conversion_eater(T const&);
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace boost::detail
|
||||||
|
|
||||||
|
#endif // ANY_CONVERSION_EATER_DWA20031117_HPP
|
1
include/boost/iterator/detail/categories.hpp
Normal file
1
include/boost/iterator/detail/categories.hpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#error obsolete
|
163
include/boost/iterator/detail/config_def.hpp
Normal file
163
include/boost/iterator/detail/config_def.hpp
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
// no include guard multiple inclusion intended
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a temporary workaround until the bulk of this is
|
||||||
|
// available in boost config.
|
||||||
|
// 23/02/03 thw
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/config.hpp> // for prior
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_ITERATOR_CONFIG_DEF
|
||||||
|
# error you have nested config_def #inclusion.
|
||||||
|
#else
|
||||||
|
# define BOOST_ITERATOR_CONFIG_DEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
||||||
|
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531))
|
||||||
|
|
||||||
|
// Recall that in general, compilers without partial specialization
|
||||||
|
// can't strip constness. Consider counting_iterator, which normally
|
||||||
|
// passes a const Value to iterator_facade. As a result, any code
|
||||||
|
// which makes a std::vector of the iterator's value_type will fail
|
||||||
|
// when its allocator declares functions overloaded on reference and
|
||||||
|
// const_reference (the same type).
|
||||||
|
//
|
||||||
|
// Furthermore, Borland 5.5.1 drops constness in enough ways that we
|
||||||
|
// end up using a proxy for operator[] when we otherwise shouldn't.
|
||||||
|
// Using reference constness gives it an extra hint that it can
|
||||||
|
// return the value_type from operator[] directly, but is not
|
||||||
|
// strictly neccessary. Not sure how best to resolve this one.
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|
||||||
|
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \
|
||||||
|
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))
|
||||||
|
# define BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
|
||||||
|
# if 0 // test code
|
||||||
|
struct v {};
|
||||||
|
|
||||||
|
typedef char (&no)[3];
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
no foo(T const&, ...);
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
char foo(T&, int);
|
||||||
|
|
||||||
|
|
||||||
|
struct value_iterator
|
||||||
|
{
|
||||||
|
v operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct lvalue_deref_helper
|
||||||
|
{
|
||||||
|
static T& x;
|
||||||
|
enum { value = (sizeof(foo(*x,0)) == 1) };
|
||||||
|
};
|
||||||
|
|
||||||
|
int z2[(lvalue_deref_helper<v*>::value == 1) ? 1 : -1];
|
||||||
|
int z[(lvalue_deref_helper<value_iterator>::value) == 1 ? -1 : 1 ];
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|
||||||
|
|| BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \
|
||||||
|
|| BOOST_WORKAROUND(__MWERKS__, <= 0x3000) \
|
||||||
|
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented"
|
||||||
|
|
||||||
|
# if 0 // test code
|
||||||
|
template <bool x>
|
||||||
|
struct bar
|
||||||
|
{
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct bar<false>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct foo : bar<(sizeof(T) == 1)>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
char* f(int, typename foo<T>::type = 0) { return 0; }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
int f(...) { return 0; }
|
||||||
|
|
||||||
|
char* x = f<char>(0);
|
||||||
|
int y = f<char[2]>(0);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||||
|
# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile:
|
||||||
|
|
||||||
|
# if 0 // test code
|
||||||
|
template <class T>
|
||||||
|
struct foo
|
||||||
|
{
|
||||||
|
foo(T);
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
foo(foo<U> const& other) : p(other.p) { }
|
||||||
|
|
||||||
|
T p;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool x = boost::is_convertible<foo<int const*>, foo<int*> >::value;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
||||||
|
|| BOOST_WORKAROUND(__MWERKS__, <= 0x2407) \
|
||||||
|
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
# define BOOST_ITERATOR_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE)
|
||||||
|
# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
# define BOOST_ARG_DEPENDENT_TYPENAME typename
|
||||||
|
# else
|
||||||
|
# define BOOST_ARG_DEPENDENT_TYPENAME
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// no include guard multiple inclusion intended
|
27
include/boost/iterator/detail/config_undef.hpp
Normal file
27
include/boost/iterator/detail/config_undef.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
// no include guard multiple inclusion intended
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a temporary workaround until the bulk of this is
|
||||||
|
// available in boost config.
|
||||||
|
// 23/02/03 thw
|
||||||
|
//
|
||||||
|
|
||||||
|
#undef BOOST_NO_SFINAE
|
||||||
|
#undef BOOST_NO_IS_CONVERTIBLE
|
||||||
|
#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE
|
||||||
|
#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||||
|
#undef BOOST_ARG_DEPENDENT_TYPENAME
|
||||||
|
#undef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
|
||||||
|
#ifdef BOOST_ITERATOR_CONFIG_DEF
|
||||||
|
# undef BOOST_ITERATOR_CONFIG_DEF
|
||||||
|
#else
|
||||||
|
# error missing or nested #include config_def
|
||||||
|
#endif
|
88
include/boost/iterator/detail/enable_if.hpp
Normal file
88
include/boost/iterator/detail/enable_if.hpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_ENABLE_IF_23022003THW_HPP
|
||||||
|
#define BOOST_ENABLE_IF_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/mpl/identity.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
//
|
||||||
|
// Boost iterators uses its own enable_if cause we need
|
||||||
|
// special semantics for deficient compilers.
|
||||||
|
// 23/02/03 thw
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace iterators
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Base machinery for all kinds of enable if
|
||||||
|
//
|
||||||
|
template<bool>
|
||||||
|
struct enabled
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct base
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// For compilers that don't support "Substitution Failure Is Not An Error"
|
||||||
|
// enable_if falls back to always enabled. See comments
|
||||||
|
// on operator implementation for consequences.
|
||||||
|
//
|
||||||
|
template<>
|
||||||
|
struct enabled<false>
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct base
|
||||||
|
{
|
||||||
|
#ifdef BOOST_NO_SFINAE
|
||||||
|
|
||||||
|
typedef T type;
|
||||||
|
|
||||||
|
// This way to do it would give a nice error message containing
|
||||||
|
// invalid overload, but has the big disadvantage that
|
||||||
|
// there is no reference to user code in the error message.
|
||||||
|
//
|
||||||
|
// struct invalid_overload;
|
||||||
|
// typedef invalid_overload type;
|
||||||
|
//
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class Cond,
|
||||||
|
class Return>
|
||||||
|
struct enable_if
|
||||||
|
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
|
||||||
|
: enabled<(Cond::value)>::template base<Return>
|
||||||
|
# else
|
||||||
|
: mpl::identity<Return>
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||||
|
typedef Return type;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace iterators
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_ENABLE_IF_23022003THW_HPP
|
214
include/boost/iterator/detail/facade_iterator_category.hpp
Executable file
214
include/boost/iterator/detail/facade_iterator_category.hpp
Executable file
@ -0,0 +1,214 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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 FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
|
||||||
|
# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
|
||||||
|
|
||||||
|
# include <boost/iterator/iterator_categories.hpp>
|
||||||
|
|
||||||
|
# include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
# include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
|
||||||
|
# include <boost/mpl/and.hpp>
|
||||||
|
# include <boost/mpl/if.hpp>
|
||||||
|
# include <boost/mpl/apply_if.hpp>
|
||||||
|
# include <boost/mpl/identity.hpp>
|
||||||
|
|
||||||
|
# include <boost/type_traits/is_same.hpp>
|
||||||
|
# include <boost/type_traits/is_const.hpp>
|
||||||
|
# include <boost/type_traits/is_reference.hpp>
|
||||||
|
# include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
# include <boost/type_traits/is_same.hpp>
|
||||||
|
|
||||||
|
# include <boost/iterator/detail/config_def.hpp> // try to keep this last
|
||||||
|
|
||||||
|
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||||
|
# include <boost/python/detail/indirect_traits.hpp>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterator_category deduction for iterator_facade
|
||||||
|
//
|
||||||
|
|
||||||
|
// forward declaration
|
||||||
|
namespace boost { struct use_default; }
|
||||||
|
|
||||||
|
namespace boost { namespace detail {
|
||||||
|
|
||||||
|
struct input_output_iterator_tag
|
||||||
|
: std::input_iterator_tag
|
||||||
|
{
|
||||||
|
// Using inheritance for only input_iterator_tag helps to avoid
|
||||||
|
// ambiguities when a stdlib implementation dispatches on a
|
||||||
|
// function which is overloaded on both input_iterator_tag and
|
||||||
|
// output_iterator_tag, as STLPort does, in its __valid_range
|
||||||
|
// function. I claim it's better to avoid the ambiguity in these
|
||||||
|
// cases.
|
||||||
|
operator std::output_iterator_tag() const
|
||||||
|
{
|
||||||
|
return std::output_iterator_tag();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// True iff the user has explicitly disabled writability of this
|
||||||
|
// iterator. Pass the iterator_facade's Value parameter and its
|
||||||
|
// nested ::reference type.
|
||||||
|
//
|
||||||
|
template <class ValueParam, class Reference>
|
||||||
|
struct iterator_writability_disabled
|
||||||
|
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
|
||||||
|
: mpl::or_<
|
||||||
|
is_const<Reference>
|
||||||
|
, python::detail::is_reference_to_const<Reference>
|
||||||
|
, is_const<ValueParam>
|
||||||
|
>
|
||||||
|
# else
|
||||||
|
: is_const<ValueParam>
|
||||||
|
# endif
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert an iterator_facade's traversal category, Value parameter,
|
||||||
|
// and ::reference type to an appropriate old-style category.
|
||||||
|
//
|
||||||
|
// If writability has been disabled per the above metafunction, the
|
||||||
|
// result will not be convertible to output_iterator_tag.
|
||||||
|
//
|
||||||
|
// Otherwise, if Traversal == single_pass_traversal_tag, the following
|
||||||
|
// conditions will result in a tag that is convertible both to
|
||||||
|
// input_iterator_tag and output_iterator_tag:
|
||||||
|
//
|
||||||
|
// 1. Reference is a reference to non-const
|
||||||
|
// 2. Reference is not a reference and is convertible to Value
|
||||||
|
//
|
||||||
|
template <class Traversal, class ValueParam, class Reference>
|
||||||
|
struct iterator_facade_default_category
|
||||||
|
: mpl::apply_if<
|
||||||
|
mpl::and_<
|
||||||
|
is_reference<Reference>
|
||||||
|
, is_convertible<Traversal,forward_traversal_tag>
|
||||||
|
>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Traversal,random_access_traversal_tag>
|
||||||
|
, mpl::identity<std::random_access_iterator_tag>
|
||||||
|
, mpl::if_<
|
||||||
|
is_convertible<Traversal,bidirectional_traversal_tag>
|
||||||
|
, std::bidirectional_iterator_tag
|
||||||
|
, std::forward_iterator_tag
|
||||||
|
>
|
||||||
|
>
|
||||||
|
, typename mpl::apply_if<
|
||||||
|
mpl::and_<
|
||||||
|
is_convertible<Traversal, single_pass_traversal_tag>
|
||||||
|
|
||||||
|
, mpl::or_< // check for readability
|
||||||
|
is_same<ValueParam,use_default>
|
||||||
|
, is_convertible<Reference, ValueParam>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
, mpl::if_<
|
||||||
|
iterator_writability_disabled<ValueParam,Reference>
|
||||||
|
, std::input_iterator_tag
|
||||||
|
, input_output_iterator_tag
|
||||||
|
>
|
||||||
|
|
||||||
|
, mpl::identity<std::output_iterator_tag>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// True iff T is convertible to an old-style iterator category.
|
||||||
|
template <class T>
|
||||||
|
struct is_iterator_category
|
||||||
|
: mpl::or_<
|
||||||
|
is_convertible<T,std::input_iterator_tag>
|
||||||
|
, is_convertible<T,std::output_iterator_tag>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_iterator_traversal
|
||||||
|
: is_convertible<T,incrementable_traversal_tag>
|
||||||
|
{};
|
||||||
|
|
||||||
|
//
|
||||||
|
// A composite iterator_category tag convertible to Category (a pure
|
||||||
|
// old-style category) and Traversal (a pure traversal tag).
|
||||||
|
// Traversal must be a strict increase of the traversal power given by
|
||||||
|
// Category.
|
||||||
|
//
|
||||||
|
template <class Category, class Traversal>
|
||||||
|
struct iterator_category_with_traversal
|
||||||
|
: Category, Traversal
|
||||||
|
{
|
||||||
|
# if 0
|
||||||
|
// Because of limitations on multiple user-defined conversions,
|
||||||
|
// this should be a good test of whether convertibility is enough
|
||||||
|
// in the spec, or whether we need to specify inheritance.
|
||||||
|
operator Category() const { return Category(); }
|
||||||
|
operator Traversal() const { return Traversal(); }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
// Make sure this isn't used to build any categories where
|
||||||
|
// convertibility to Traversal is redundant. Should just use the
|
||||||
|
// Category element in that case.
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
!(is_convertible<
|
||||||
|
typename iterator_category_to_traversal<Category>::type
|
||||||
|
, Traversal
|
||||||
|
>::value));
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(is_iterator_category<Category>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!is_iterator_traversal<Category>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_iterator_traversal<Traversal>::value);
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Computes an iterator_category tag whose traversal is Traversal and
|
||||||
|
// which is appropriate for an iterator
|
||||||
|
template <class Traversal, class ValueParam, class Reference>
|
||||||
|
struct facade_iterator_category_impl
|
||||||
|
{
|
||||||
|
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
typedef typename iterator_facade_default_category<
|
||||||
|
Traversal,ValueParam,Reference
|
||||||
|
>::type category;
|
||||||
|
|
||||||
|
typedef typename mpl::if_<
|
||||||
|
is_same<
|
||||||
|
Traversal
|
||||||
|
, typename iterator_category_to_traversal<category>::type
|
||||||
|
>
|
||||||
|
, category
|
||||||
|
, iterator_category_with_traversal<category,Traversal>
|
||||||
|
>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Compute an iterator_category for iterator_facade
|
||||||
|
//
|
||||||
|
template <class CategoryOrTraversal, class ValueParam, class Reference>
|
||||||
|
struct facade_iterator_category
|
||||||
|
: mpl::apply_if<
|
||||||
|
is_iterator_category<CategoryOrTraversal>
|
||||||
|
, mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
|
||||||
|
, facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace boost::detail
|
||||||
|
|
||||||
|
# include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
|
98
include/boost/iterator/detail/minimum_category.hpp
Executable file
98
include/boost/iterator/detail/minimum_category.hpp
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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 MINIMUM_CATEGORY_DWA20031119_HPP
|
||||||
|
# define MINIMUM_CATEGORY_DWA20031119_HPP
|
||||||
|
|
||||||
|
# include <boost/type_traits/is_convertible.hpp>
|
||||||
|
# include <boost/type_traits/is_same.hpp>
|
||||||
|
|
||||||
|
# include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
|
||||||
|
namespace boost { namespace detail {
|
||||||
|
//
|
||||||
|
// Returns the minimum category type or error_type
|
||||||
|
// if T1 and T2 are unrelated.
|
||||||
|
//
|
||||||
|
// For compilers not supporting is_convertible this only
|
||||||
|
// works with the new boost return and traversal category
|
||||||
|
// types. The exact boost _types_ are required. No derived types
|
||||||
|
// will work.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
template <bool GreaterEqual, bool LessEqual>
|
||||||
|
struct minimum_category_impl;
|
||||||
|
|
||||||
|
template <class T1, class T2>
|
||||||
|
struct error_not_related_by_convertibility;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct minimum_category_impl<true,false>
|
||||||
|
{
|
||||||
|
template <class T1, class T2> struct apply
|
||||||
|
{
|
||||||
|
typedef T2 type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct minimum_category_impl<false,true>
|
||||||
|
{
|
||||||
|
template <class T1, class T2> struct apply
|
||||||
|
{
|
||||||
|
typedef T1 type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct minimum_category_impl<true,true>
|
||||||
|
{
|
||||||
|
template <class T1, class T2> struct apply
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT((is_same<T1,T2>::value));
|
||||||
|
typedef T1 type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct minimum_category_impl<false,false>
|
||||||
|
{
|
||||||
|
template <class T1, class T2> struct apply
|
||||||
|
: error_not_related_by_convertibility<T1,T2>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T1 = mpl::_1, class T2 = mpl::_2>
|
||||||
|
struct minimum_category
|
||||||
|
{
|
||||||
|
typedef minimum_category_impl<
|
||||||
|
::boost::is_convertible<T1,T2>::value
|
||||||
|
, ::boost::is_convertible<T2,T1>::value
|
||||||
|
> outer;
|
||||||
|
|
||||||
|
typedef typename outer::template apply<T1,T2> inner;
|
||||||
|
typedef typename inner::type type;
|
||||||
|
|
||||||
|
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct minimum_category<mpl::_1,mpl::_2>
|
||||||
|
{
|
||||||
|
template <class T1, class T2>
|
||||||
|
struct apply : minimum_category<T1,T2>
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
template <>
|
||||||
|
struct minimum_category<int,int>
|
||||||
|
{
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
}} // namespace boost::detail
|
||||||
|
|
||||||
|
#endif // MINIMUM_CATEGORY_DWA20031119_HPP
|
137
include/boost/iterator/filter_iterator.hpp
Normal file
137
include/boost/iterator/filter_iterator.hpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_FILTER_ITERATOR_23022003THW_HPP
|
||||||
|
#define BOOST_FILTER_ITERATOR_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/is_class.hpp>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
template <class Predicate, class Iterator>
|
||||||
|
class filter_iterator;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class Predicate, class Iterator>
|
||||||
|
struct filter_iterator_base
|
||||||
|
{
|
||||||
|
typedef iterator_adaptor<
|
||||||
|
filter_iterator<Predicate, Iterator>
|
||||||
|
, Iterator
|
||||||
|
, use_default
|
||||||
|
, typename mpl::if_<
|
||||||
|
is_convertible<
|
||||||
|
typename iterator_traversal<Iterator>::type
|
||||||
|
, bidirectional_traversal_tag
|
||||||
|
>
|
||||||
|
, forward_traversal_tag
|
||||||
|
, use_default
|
||||||
|
>::type
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Predicate, class Iterator>
|
||||||
|
class filter_iterator
|
||||||
|
: public detail::filter_iterator_base<Predicate, Iterator>::type
|
||||||
|
{
|
||||||
|
typedef typename detail::filter_iterator_base<
|
||||||
|
Predicate, Iterator
|
||||||
|
>::type super_t;
|
||||||
|
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
public:
|
||||||
|
filter_iterator() { }
|
||||||
|
|
||||||
|
filter_iterator(Predicate f, Iterator x, Iterator end = Iterator())
|
||||||
|
: super_t(x), m_predicate(f), m_end(end)
|
||||||
|
{
|
||||||
|
satisfy_predicate();
|
||||||
|
}
|
||||||
|
|
||||||
|
filter_iterator(Iterator x, Iterator end = Iterator())
|
||||||
|
: super_t(x), m_predicate(), m_end(end)
|
||||||
|
{
|
||||||
|
// Pro8 is a little too aggressive about instantiating the
|
||||||
|
// body of this function.
|
||||||
|
#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||||
|
// Don't allow use of this constructor if Predicate is a
|
||||||
|
// function pointer type, since it will be 0.
|
||||||
|
BOOST_STATIC_ASSERT(is_class<Predicate>::value);
|
||||||
|
#endif
|
||||||
|
satisfy_predicate();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class OtherIterator>
|
||||||
|
filter_iterator(
|
||||||
|
filter_iterator<Predicate, OtherIterator> const& t
|
||||||
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {}
|
||||||
|
|
||||||
|
Predicate predicate() const { return m_predicate; }
|
||||||
|
|
||||||
|
Iterator end() const { return m_end; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void increment()
|
||||||
|
{
|
||||||
|
++(this->base_reference());
|
||||||
|
satisfy_predicate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrement()
|
||||||
|
{
|
||||||
|
while(!this->m_predicate(*--(this->base_reference()))){};
|
||||||
|
}
|
||||||
|
|
||||||
|
void satisfy_predicate()
|
||||||
|
{
|
||||||
|
while (this->base() != this->m_end && !this->m_predicate(*this->base()))
|
||||||
|
++(this->base_reference());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probably should be the initial base class so it can be
|
||||||
|
// optimized away via EBO if it is an empty class.
|
||||||
|
Predicate m_predicate;
|
||||||
|
Iterator m_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Predicate, class Iterator>
|
||||||
|
filter_iterator<Predicate,Iterator>
|
||||||
|
make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator())
|
||||||
|
{
|
||||||
|
return filter_iterator<Predicate,Iterator>(f,x,end);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Predicate, class Iterator>
|
||||||
|
filter_iterator<Predicate,Iterator>
|
||||||
|
make_filter_iterator(
|
||||||
|
typename iterators::enable_if<
|
||||||
|
is_class<Predicate>
|
||||||
|
, Iterator
|
||||||
|
>::type x
|
||||||
|
, Iterator end = Iterator()
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
, Predicate* = 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return filter_iterator<Predicate,Iterator>(x,end);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP
|
251
include/boost/iterator/indirect_iterator.hpp
Normal file
251
include/boost/iterator/indirect_iterator.hpp
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_INDIRECT_ITERATOR_23022003THW_HPP
|
||||||
|
#define BOOST_INDIRECT_ITERATOR_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_traits.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
|
|
||||||
|
#include <boost/python/detail/indirect_traits.hpp>
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/mpl/identity.hpp>
|
||||||
|
#include <boost/mpl/apply_if.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
|
#include <boost/mpl/aux_/has_xxx.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_MPL_NO_AUX_HAS_XXX
|
||||||
|
# include <boost/shared_ptr.hpp>
|
||||||
|
# include <boost/scoped_ptr.hpp>
|
||||||
|
# include <boost/mpl/bool.hpp>
|
||||||
|
# include <memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_def.hpp> // must be last #include
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
template <class Iter, class Value, class Category, class Reference, class Difference>
|
||||||
|
class indirect_iterator;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct referent;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct unspecified {};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Detection for whether a type has a nested `element_type'
|
||||||
|
// typedef. Used to detect smart pointers. For compilers not
|
||||||
|
// supporting mpl's has_xxx, we supply specializations. However, we
|
||||||
|
// really ought to have a specializable is_pointer template which
|
||||||
|
// can be used instead with something like
|
||||||
|
// boost/python/pointee.hpp to find the value_type.
|
||||||
|
//
|
||||||
|
# ifndef BOOST_MPL_NO_AUX_HAS_XXX
|
||||||
|
namespace aux
|
||||||
|
{
|
||||||
|
BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type
|
||||||
|
: mpl::bool_<
|
||||||
|
mpl::if_<
|
||||||
|
is_class<T>
|
||||||
|
, ::boost::detail::aux::has_element_type<T>
|
||||||
|
, mpl::false_
|
||||||
|
>::type::value
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
# else
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type
|
||||||
|
: mpl::false_ {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type<boost::shared_ptr<T> >
|
||||||
|
: mpl::true_ {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type<boost::scoped_ptr<T> >
|
||||||
|
: mpl::true_ {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type<std::auto_ptr<T> >
|
||||||
|
: mpl::true_ {};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// Metafunction accessing the nested ::element_type
|
||||||
|
template <class T>
|
||||||
|
struct element_type
|
||||||
|
: mpl::identity<typename T::element_type>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct iterator_is_mutable
|
||||||
|
: mpl::not_<
|
||||||
|
boost::python::detail::is_reference_to_const<
|
||||||
|
typename iterator_reference<T>::type
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct not_int_impl
|
||||||
|
{
|
||||||
|
template <class U>
|
||||||
|
struct apply {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct not_int_impl<int> {};
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
struct not_int
|
||||||
|
: not_int_impl<T>::template apply<U> {};
|
||||||
|
|
||||||
|
|
||||||
|
template <class Dereferenceable>
|
||||||
|
struct class_has_element_type
|
||||||
|
: mpl::and_<
|
||||||
|
is_class<Dereferenceable>
|
||||||
|
, has_element_type<Dereferenceable>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// If the Value parameter is unspecified, we use this metafunction
|
||||||
|
// to deduce the default types
|
||||||
|
template <class Dereferenceable>
|
||||||
|
struct default_indirect_value
|
||||||
|
{
|
||||||
|
typedef typename remove_cv<
|
||||||
|
typename referent<Dereferenceable>::type
|
||||||
|
>::type referent_t;
|
||||||
|
|
||||||
|
typedef typename mpl::if_<
|
||||||
|
mpl::or_<
|
||||||
|
class_has_element_type<Dereferenceable>
|
||||||
|
, iterator_is_mutable<Dereferenceable>
|
||||||
|
>
|
||||||
|
, referent_t
|
||||||
|
, referent_t const
|
||||||
|
>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iter, class Value, class Category, class Reference, class Difference>
|
||||||
|
struct indirect_base
|
||||||
|
{
|
||||||
|
typedef typename iterator_traits<Iter>::value_type dereferenceable;
|
||||||
|
|
||||||
|
typedef iterator_adaptor<
|
||||||
|
indirect_iterator<Iter, Value, Category, Reference, Difference>
|
||||||
|
, Iter
|
||||||
|
, typename ia_dflt_help<
|
||||||
|
Value, default_indirect_value<dereferenceable>
|
||||||
|
>::type
|
||||||
|
, Category
|
||||||
|
, Reference
|
||||||
|
, Difference
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct indirect_base<int, int, int, int, int> {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// User-specializable metafunction which returns the referent of a
|
||||||
|
// dereferenceable type. The default implementation returns
|
||||||
|
// Dereferenceable::element_type if such a member exists (thus
|
||||||
|
// handling the boost smart pointers and auto_ptr), and
|
||||||
|
// iterator_traits<Dereferenceable>::value_type otherwise.
|
||||||
|
template <class Dereferenceable>
|
||||||
|
struct referent
|
||||||
|
: mpl::apply_if<
|
||||||
|
detail::class_has_element_type<Dereferenceable>
|
||||||
|
, detail::element_type<Dereferenceable>
|
||||||
|
, iterator_value<Dereferenceable>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Iterator
|
||||||
|
, class Value = use_default
|
||||||
|
, class Category = use_default
|
||||||
|
, class Reference = use_default
|
||||||
|
, class Difference = use_default
|
||||||
|
>
|
||||||
|
class indirect_iterator
|
||||||
|
: public detail::indirect_base<
|
||||||
|
Iterator, Value, Category, Reference, Difference
|
||||||
|
>::type
|
||||||
|
{
|
||||||
|
typedef typename detail::indirect_base<
|
||||||
|
Iterator, Value, Category, Reference, Difference
|
||||||
|
>::type super_t;
|
||||||
|
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
public:
|
||||||
|
indirect_iterator() {}
|
||||||
|
|
||||||
|
indirect_iterator(Iterator iter)
|
||||||
|
: super_t(iter) {}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Iterator2, class Value2, class Category2
|
||||||
|
, class Reference2, class Difference2
|
||||||
|
>
|
||||||
|
indirect_iterator(
|
||||||
|
indirect_iterator<
|
||||||
|
Iterator2, Value2, Category2, Reference2, Difference2
|
||||||
|
> const& y
|
||||||
|
, typename enable_if_convertible<Iterator2, Iterator>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(y.base())
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename super_t::reference dereference() const
|
||||||
|
{
|
||||||
|
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
return const_cast<super_t::reference>(**this->base());
|
||||||
|
# else
|
||||||
|
return **this->base();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
inline
|
||||||
|
indirect_iterator<Iter> make_indirect_iterator(Iter x)
|
||||||
|
{
|
||||||
|
return indirect_iterator<Iter>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Traits, class Iter>
|
||||||
|
inline
|
||||||
|
indirect_iterator<Iter,Traits> make_indirect_iterator(Iter x, Traits* = 0)
|
||||||
|
{
|
||||||
|
return indirect_iterator<Iter, Traits>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_INDIRECT_ITERATOR_23022003THW_HPP
|
52
include/boost/iterator/interoperable.hpp
Normal file
52
include/boost/iterator/interoperable.hpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_INTEROPERABLE_23022003THW_HPP
|
||||||
|
# define BOOST_INTEROPERABLE_23022003THW_HPP
|
||||||
|
|
||||||
|
# include <boost/mpl/bool.hpp>
|
||||||
|
# include <boost/mpl/or.hpp>
|
||||||
|
|
||||||
|
# include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
# include <boost/iterator/detail/config_def.hpp> // must appear last
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// Meta function that determines whether two
|
||||||
|
// iterator types are considered interoperable.
|
||||||
|
//
|
||||||
|
// Two iterator types A,B are considered interoperable if either
|
||||||
|
// A is convertible to B or vice versa.
|
||||||
|
// This interoperability definition is in sync with the
|
||||||
|
// standards requirements on constant/mutable container
|
||||||
|
// iterators (23.1 [lib.container.requirements]).
|
||||||
|
//
|
||||||
|
// For compilers that don't support is_convertible
|
||||||
|
// is_interoperable gives false positives. See comments
|
||||||
|
// on operator implementation for consequences.
|
||||||
|
//
|
||||||
|
template <typename A, typename B>
|
||||||
|
struct is_interoperable
|
||||||
|
# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||||
|
: mpl::true_
|
||||||
|
# else
|
||||||
|
: mpl::or_<
|
||||||
|
is_convertible< A, B >
|
||||||
|
, is_convertible< B, A > >
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
# include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_INTEROPERABLE_23022003THW_HPP
|
150
include/boost/iterator/is_lvalue_iterator.hpp
Executable file
150
include/boost/iterator/is_lvalue_iterator.hpp
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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 IS_LVALUE_ITERATOR_DWA2003112_HPP
|
||||||
|
# define IS_LVALUE_ITERATOR_DWA2003112_HPP
|
||||||
|
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/detail/iterator.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
||||||
|
|
||||||
|
// should be the last #includes
|
||||||
|
#include <boost/type_traits/detail/bool_trait_def.hpp>
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_IS_CONVERTIBLE
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
// Calling lvalue_preserver( <expression>, 0 ) returns a reference
|
||||||
|
// to the expression's result if <expression> is an lvalue, or
|
||||||
|
// not_an_lvalue() otherwise.
|
||||||
|
struct not_an_lvalue {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T& lvalue_preserver(T&, int);
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
not_an_lvalue lvalue_preserver(U const&, ...);
|
||||||
|
|
||||||
|
# define BOOST_LVALUE_PRESERVER(expr) lvalue_preserver(expr,0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define BOOST_LVALUE_PRESERVER(expr) expr
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Guts of is_lvalue_iterator. Value is the iterator's value_type
|
||||||
|
// and the result is computed in the nested rebind template.
|
||||||
|
template <class Value>
|
||||||
|
struct is_lvalue_iterator_impl
|
||||||
|
{
|
||||||
|
// Eat implicit conversions so we don't report true for things
|
||||||
|
// convertible to Value const&
|
||||||
|
struct conversion_eater
|
||||||
|
{
|
||||||
|
conversion_eater(Value&);
|
||||||
|
};
|
||||||
|
|
||||||
|
static char tester(conversion_eater, int);
|
||||||
|
static char (& tester(any_conversion_eater, ...) )[2];
|
||||||
|
|
||||||
|
template <class It>
|
||||||
|
struct rebind
|
||||||
|
{
|
||||||
|
static It& x;
|
||||||
|
|
||||||
|
BOOST_STATIC_CONSTANT(
|
||||||
|
bool
|
||||||
|
, value = (
|
||||||
|
sizeof(
|
||||||
|
is_lvalue_iterator_impl<Value>::tester(
|
||||||
|
BOOST_LVALUE_PRESERVER(*x), 0
|
||||||
|
)
|
||||||
|
) == 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef BOOST_LVALUE_PRESERVER
|
||||||
|
|
||||||
|
//
|
||||||
|
// void specializations to handle std input and output iterators
|
||||||
|
//
|
||||||
|
template <>
|
||||||
|
struct is_lvalue_iterator_impl<void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
|
||||||
|
template <>
|
||||||
|
struct is_lvalue_iterator_impl<const void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_lvalue_iterator_impl<volatile void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_lvalue_iterator_impl<const volatile void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// This level of dispatching is required for Borland. We might save
|
||||||
|
// an instantiation by removing it for others.
|
||||||
|
//
|
||||||
|
template <class It>
|
||||||
|
struct is_readable_lvalue_iterator_impl
|
||||||
|
: is_lvalue_iterator_impl<
|
||||||
|
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type const
|
||||||
|
>::template rebind<It>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <class It>
|
||||||
|
struct is_non_const_lvalue_iterator_impl
|
||||||
|
: is_lvalue_iterator_impl<
|
||||||
|
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type
|
||||||
|
>::template rebind<It>
|
||||||
|
{};
|
||||||
|
} // 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::detail::is_readable_lvalue_iterator_impl<T>::value)
|
||||||
|
|
||||||
|
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
|
||||||
|
is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl<T>::value)
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
#include <boost/type_traits/detail/bool_trait_undef.hpp>
|
||||||
|
|
||||||
|
#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP
|
108
include/boost/iterator/is_readable_iterator.hpp
Executable file
108
include/boost/iterator/is_readable_iterator.hpp
Executable file
@ -0,0 +1,108 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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 IS_READABLE_ITERATOR_DWA2003112_HPP
|
||||||
|
# define IS_READABLE_ITERATOR_DWA2003112_HPP
|
||||||
|
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/detail/iterator.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/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_IS_CONVERTIBLE
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// Guts of is_readable_iterator. Value is the iterator's value_type
|
||||||
|
// and the result is computed in the nested rebind template.
|
||||||
|
template <class Value>
|
||||||
|
struct is_readable_iterator_impl
|
||||||
|
{
|
||||||
|
static char tester(Value&, int);
|
||||||
|
static char (& tester(any_conversion_eater, ...) )[2];
|
||||||
|
|
||||||
|
template <class It>
|
||||||
|
struct rebind
|
||||||
|
{
|
||||||
|
static It& x;
|
||||||
|
|
||||||
|
BOOST_STATIC_CONSTANT(
|
||||||
|
bool
|
||||||
|
, value = (
|
||||||
|
sizeof(
|
||||||
|
is_readable_iterator_impl<Value>::tester(*x, 1)
|
||||||
|
) == 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef BOOST_READABLE_PRESERVER
|
||||||
|
|
||||||
|
//
|
||||||
|
// void specializations to handle std input and output iterators
|
||||||
|
//
|
||||||
|
template <>
|
||||||
|
struct is_readable_iterator_impl<void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
|
||||||
|
template <>
|
||||||
|
struct is_readable_iterator_impl<const void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_readable_iterator_impl<volatile void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_readable_iterator_impl<const volatile void>
|
||||||
|
{
|
||||||
|
template <class It>
|
||||||
|
struct rebind : boost::mpl::false_
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// This level of dispatching is required for Borland. We might save
|
||||||
|
// an instantiation by removing it for others.
|
||||||
|
//
|
||||||
|
template <class It>
|
||||||
|
struct is_readable_iterator_impl2
|
||||||
|
: is_readable_iterator_impl<
|
||||||
|
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type const
|
||||||
|
>::template rebind<It>
|
||||||
|
{};
|
||||||
|
} // 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::detail::is_readable_iterator_impl2<T>::value)
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // IS_READABLE_ITERATOR_DWA2003112_HPP
|
345
include/boost/iterator/iterator_adaptor.hpp
Normal file
345
include/boost/iterator/iterator_adaptor.hpp
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
|
||||||
|
#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/detail/iterator.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
|
#include <boost/iterator/detail/enable_if.hpp>
|
||||||
|
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
|
#include <boost/mpl/or.hpp>
|
||||||
|
|
||||||
|
#include <boost/python/detail/is_xxx.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||||
|
# include <boost/type_traits/remove_reference.hpp>
|
||||||
|
#else
|
||||||
|
# include <boost/type_traits/add_reference.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_traits.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
// Used as a default template argument internally, merely to
|
||||||
|
// indicate "use the default", this can also be passed by users
|
||||||
|
// explicitly in order to specify that the default should be used.
|
||||||
|
struct use_default;
|
||||||
|
|
||||||
|
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
// the incompleteness of use_default causes massive problems for
|
||||||
|
// is_convertible (naturally). This workaround is fortunately not
|
||||||
|
// needed for vc6/vc7.
|
||||||
|
template<class To>
|
||||||
|
struct is_convertible<use_default,To>
|
||||||
|
: mpl::false_ {};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
// Result type used in enable_if_convertible meta function.
|
||||||
|
// This can be an incomplete type, as only pointers to
|
||||||
|
// enable_if_convertible< ... >::type are used.
|
||||||
|
// We could have used void for this, but conversion to
|
||||||
|
// void* is just to easy.
|
||||||
|
//
|
||||||
|
struct enable_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// enable_if for use in adapted iterators constructors.
|
||||||
|
//
|
||||||
|
// In order to provide interoperability between adapted constant and
|
||||||
|
// mutable iterators, adapted iterators will usually provide templated
|
||||||
|
// conversion constructors of the following form
|
||||||
|
//
|
||||||
|
// template <class BaseIterator>
|
||||||
|
// class adapted_iterator :
|
||||||
|
// public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
|
||||||
|
// {
|
||||||
|
// public:
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// template <class OtherIterator>
|
||||||
|
// adapted_iterator(
|
||||||
|
// OtherIterator const& it
|
||||||
|
// , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// enable_if_convertible is used to remove those overloads from the overload
|
||||||
|
// set that cannot be instantiated. For all practical purposes only overloads
|
||||||
|
// for constant/mutable interaction will remain. This has the advantage that
|
||||||
|
// meta functions like boost::is_convertible do not return false positives,
|
||||||
|
// as they can only look at the signature of the conversion constructor
|
||||||
|
// and not at the actual instantiation.
|
||||||
|
//
|
||||||
|
// enable_if_interoperable can be safely used in user code. It falls back to
|
||||||
|
// always enabled for compilers that don't support enable_if or is_convertible.
|
||||||
|
// There is no need for compiler specific workarounds in user code.
|
||||||
|
//
|
||||||
|
// The operators implementation relies on boost::is_convertible not returning
|
||||||
|
// false positives for user/library defined iterator types. See comments
|
||||||
|
// on operator implementation for consequences.
|
||||||
|
//
|
||||||
|
# if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
|
||||||
|
|
||||||
|
template <class From, class To>
|
||||||
|
struct enable_if_convertible
|
||||||
|
{
|
||||||
|
typedef detail::enable_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
# elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
|
||||||
|
|
||||||
|
// For some reason vc7.1 needs us to "cut off" instantiation
|
||||||
|
// of is_convertible in a few cases.
|
||||||
|
template<typename From, typename To>
|
||||||
|
struct enable_if_convertible
|
||||||
|
: iterators::enable_if<
|
||||||
|
mpl::or_<
|
||||||
|
is_same<From,To>
|
||||||
|
, is_convertible<From, To>
|
||||||
|
>
|
||||||
|
, detail::enable_type
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
template<typename From, typename To>
|
||||||
|
struct enable_if_convertible
|
||||||
|
: iterators::enable_if<
|
||||||
|
is_convertible<From, To>
|
||||||
|
, detail::enable_type
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Default template argument handling for iterator_adaptor
|
||||||
|
//
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// If T is use_default, return the result of invoking
|
||||||
|
// DefaultNullaryFn, otherwise return T.
|
||||||
|
template <class T, class DefaultNullaryFn>
|
||||||
|
struct ia_dflt_help
|
||||||
|
: mpl::apply_if<
|
||||||
|
is_same<T, use_default>
|
||||||
|
, DefaultNullaryFn
|
||||||
|
, mpl::identity<T>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// A metafunction which computes an iterator_adaptor's base class,
|
||||||
|
// a specialization of iterator_facade.
|
||||||
|
template <
|
||||||
|
class Derived
|
||||||
|
, class Base
|
||||||
|
, class Value
|
||||||
|
, class Traversal
|
||||||
|
, class Reference
|
||||||
|
, class Difference
|
||||||
|
>
|
||||||
|
struct iterator_adaptor_base
|
||||||
|
{
|
||||||
|
typedef iterator_facade<
|
||||||
|
Derived
|
||||||
|
|
||||||
|
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||||
|
, typename detail::ia_dflt_help<
|
||||||
|
Value
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_same<Reference,use_default>
|
||||||
|
, iterator_value<Base>
|
||||||
|
, remove_reference<Reference>
|
||||||
|
>
|
||||||
|
>::type
|
||||||
|
# else
|
||||||
|
, typename detail::ia_dflt_help<
|
||||||
|
Value, iterator_value<Base>
|
||||||
|
>::type
|
||||||
|
# endif
|
||||||
|
|
||||||
|
, typename detail::ia_dflt_help<
|
||||||
|
Traversal
|
||||||
|
, iterator_traversal<Base>
|
||||||
|
>::type
|
||||||
|
|
||||||
|
, typename detail::ia_dflt_help<
|
||||||
|
Reference
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_same<Value,use_default>
|
||||||
|
, iterator_reference<Base>
|
||||||
|
, add_reference<Value>
|
||||||
|
>
|
||||||
|
>::type
|
||||||
|
|
||||||
|
, typename detail::ia_dflt_help<
|
||||||
|
Difference, iterator_difference<Base>
|
||||||
|
>::type
|
||||||
|
>
|
||||||
|
type;
|
||||||
|
};
|
||||||
|
template <class T> int static_assert_convertible_to(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Iterator Adaptor
|
||||||
|
//
|
||||||
|
// The parameter ordering changed slightly with respect to former
|
||||||
|
// versions of iterator_adaptor The idea is that when the user needs
|
||||||
|
// to fiddle with the reference type it is highly likely that the
|
||||||
|
// iterator category has to be adjusted as well. Any of the
|
||||||
|
// following four template arguments may be ommitted or explicitly
|
||||||
|
// replaced by use_default.
|
||||||
|
//
|
||||||
|
// Value - if supplied, the value_type of the resulting iterator, unless
|
||||||
|
// const. If const, a conforming compiler strips constness for the
|
||||||
|
// value_type. If not supplied, iterator_traits<Base>::value_type is used
|
||||||
|
//
|
||||||
|
// Category - the traversal category of the resulting iterator. If not
|
||||||
|
// supplied, iterator_traversal<Base>::type is used.
|
||||||
|
//
|
||||||
|
// Reference - the reference type of the resulting iterator, and in
|
||||||
|
// particular, the result type of operator*(). If not supplied but
|
||||||
|
// Value is supplied, Value& is used. Otherwise
|
||||||
|
// iterator_traits<Base>::reference is used.
|
||||||
|
//
|
||||||
|
// Difference - the difference_type of the resulting iterator. If not
|
||||||
|
// supplied, iterator_traits<Base>::difference_type is used.
|
||||||
|
//
|
||||||
|
template <
|
||||||
|
class Derived
|
||||||
|
, class Base
|
||||||
|
, class Value = use_default
|
||||||
|
, class Traversal = use_default
|
||||||
|
, class Reference = use_default
|
||||||
|
, class Difference = use_default
|
||||||
|
>
|
||||||
|
class iterator_adaptor
|
||||||
|
: public detail::iterator_adaptor_base<
|
||||||
|
Derived, Base, Value, Traversal, Reference, Difference
|
||||||
|
>::type
|
||||||
|
{
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
typedef typename detail::iterator_adaptor_base<
|
||||||
|
Derived, Base, Value, Traversal, Reference, Difference
|
||||||
|
>::type super_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
iterator_adaptor() {}
|
||||||
|
|
||||||
|
explicit iterator_adaptor(Base iter)
|
||||||
|
: m_iterator(iter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Base base() const
|
||||||
|
{ return m_iterator; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//
|
||||||
|
// lvalue access to the Base object for Derived
|
||||||
|
//
|
||||||
|
Base const& base_reference() const
|
||||||
|
{ return m_iterator; }
|
||||||
|
|
||||||
|
Base& base_reference()
|
||||||
|
{ return m_iterator; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
//
|
||||||
|
// Core iterator interface for iterator_facade. This is private
|
||||||
|
// to prevent temptation for Derived classes to use it, which
|
||||||
|
// will often result in an error. Derived classes should use
|
||||||
|
// base_reference(), above, to get direct access to m_iterator.
|
||||||
|
//
|
||||||
|
typename super_t::reference dereference() const
|
||||||
|
{ return *m_iterator; }
|
||||||
|
|
||||||
|
template <
|
||||||
|
class OtherDerived, class OtherIterator, class V, class C, class R, class D
|
||||||
|
>
|
||||||
|
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
|
||||||
|
{
|
||||||
|
// Maybe readd with same_distance
|
||||||
|
// BOOST_STATIC_ASSERT(
|
||||||
|
// (detail::same_category_and_difference<Derived,OtherDerived>::value)
|
||||||
|
// );
|
||||||
|
return m_iterator == x.base();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef typename iterator_category_to_traversal<
|
||||||
|
typename super_t::iterator_category
|
||||||
|
>::type my_traversal;
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
|
||||||
|
typedef int assertion[sizeof(detail::static_assert_convertible_to<cat>(my_traversal()))];
|
||||||
|
// BOOST_STATIC_ASSERT((is_convertible<my_traversal,cat>::value));
|
||||||
|
|
||||||
|
void advance(typename super_t::difference_type n)
|
||||||
|
{
|
||||||
|
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
|
||||||
|
m_iterator += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment() { ++m_iterator; }
|
||||||
|
|
||||||
|
void decrement()
|
||||||
|
{
|
||||||
|
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
|
||||||
|
--m_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class OtherDerived, class OtherIterator, class V, class C, class R, class D
|
||||||
|
>
|
||||||
|
typename super_t::difference_type distance_to(
|
||||||
|
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
|
||||||
|
{
|
||||||
|
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
|
||||||
|
// Maybe readd with same_distance
|
||||||
|
// BOOST_STATIC_ASSERT(
|
||||||
|
// (detail::same_category_and_difference<Derived,OtherDerived>::value)
|
||||||
|
// );
|
||||||
|
return y.base() - m_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
|
||||||
|
|
||||||
|
private: // data members
|
||||||
|
Base m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
|
458
include/boost/iterator/iterator_archetypes.hpp
Normal file
458
include/boost/iterator/iterator_archetypes.hpp
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
#ifndef BOOST_ITERATOR_ARCHETYPES_HPP
|
||||||
|
#define BOOST_ITERATOR_ARCHETYPES_HPP
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
#include <boost/operators.hpp>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/facade_iterator_category.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/is_const.hpp>
|
||||||
|
#include <boost/type_traits/add_const.hpp>
|
||||||
|
#include <boost/type_traits/remove_const.hpp>
|
||||||
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
|
|
||||||
|
#include <boost/mpl/aux_/msvc_eti_base.hpp>
|
||||||
|
#include <boost/mpl/bitand.hpp>
|
||||||
|
#include <boost/mpl/int.hpp>
|
||||||
|
#include <boost/mpl/equal_to.hpp>
|
||||||
|
#include <boost/mpl/if.hpp>
|
||||||
|
#include <boost/mpl/apply_if.hpp>
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/identity.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template <class Value, class AccessCategory>
|
||||||
|
struct access_archetype;
|
||||||
|
|
||||||
|
template <class Derived, class Value, class AccessCategory, class TraversalCategory>
|
||||||
|
struct traversal_archetype;
|
||||||
|
|
||||||
|
namespace iterator_archetypes
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
readable_iterator_bit = 1
|
||||||
|
, writable_iterator_bit = 2
|
||||||
|
, swappable_iterator_bit = 4
|
||||||
|
, lvalue_iterator_bit = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
// Not quite tags, since dispatching wouldn't work.
|
||||||
|
typedef mpl::int_<readable_iterator_bit>::type readable_iterator_t;
|
||||||
|
typedef mpl::int_<writable_iterator_bit>::type writable_iterator_t;
|
||||||
|
|
||||||
|
typedef mpl::int_<
|
||||||
|
(readable_iterator_bit|writable_iterator_bit)
|
||||||
|
>::type readable_writable_iterator_t;
|
||||||
|
|
||||||
|
typedef mpl::int_<
|
||||||
|
(readable_iterator_bit|lvalue_iterator_bit)
|
||||||
|
>::type readable_lvalue_iterator_t;
|
||||||
|
|
||||||
|
typedef mpl::int_<
|
||||||
|
(lvalue_iterator_bit|writable_iterator_bit)
|
||||||
|
>::type writable_lvalue_iterator_t;
|
||||||
|
|
||||||
|
typedef mpl::int_<swappable_iterator_bit>::type swappable_iterator_t;
|
||||||
|
typedef mpl::int_<lvalue_iterator_bit>::type lvalue_iterator_t;
|
||||||
|
|
||||||
|
template <class Derived, class Base>
|
||||||
|
struct has_access
|
||||||
|
: mpl::equal_to<
|
||||||
|
mpl::bitand_<Derived,Base>
|
||||||
|
, Base
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct assign_proxy
|
||||||
|
{
|
||||||
|
assign_proxy& operator=(T);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct read_proxy
|
||||||
|
{
|
||||||
|
operator T();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct read_write_proxy
|
||||||
|
: assign_proxy<T>
|
||||||
|
, read_proxy<T>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct arrow_proxy
|
||||||
|
{
|
||||||
|
T const* operator->() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct no_operator_brackets {};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct readable_operator_brackets
|
||||||
|
{
|
||||||
|
read_proxy<ValueType> operator[](std::ptrdiff_t n) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct writable_operator_brackets
|
||||||
|
{
|
||||||
|
read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Value, class AccessCategory, class TraversalCategory>
|
||||||
|
struct operator_brackets
|
||||||
|
: mpl::aux::msvc_eti_base<
|
||||||
|
typename mpl::apply_if<
|
||||||
|
is_convertible<TraversalCategory, random_access_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
iterator_archetypes::has_access<
|
||||||
|
AccessCategory
|
||||||
|
, iterator_archetypes::writable_iterator_t
|
||||||
|
>
|
||||||
|
, mpl::identity<writable_operator_brackets<Value> >
|
||||||
|
, mpl::if_<
|
||||||
|
iterator_archetypes::has_access<
|
||||||
|
AccessCategory
|
||||||
|
, iterator_archetypes::readable_iterator_t
|
||||||
|
>
|
||||||
|
, readable_operator_brackets<Value>
|
||||||
|
, no_operator_brackets
|
||||||
|
>
|
||||||
|
>
|
||||||
|
, mpl::identity<no_operator_brackets>
|
||||||
|
>::type
|
||||||
|
>::type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <class TraversalCategory>
|
||||||
|
struct traversal_archetype_impl
|
||||||
|
{
|
||||||
|
template <class Derived,class Value> struct archetype;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Derived, class Value, class TraversalCategory>
|
||||||
|
struct traversal_archetype_
|
||||||
|
: mpl::aux::msvc_eti_base<
|
||||||
|
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
||||||
|
>::type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct traversal_archetype_impl<incrementable_traversal_tag>
|
||||||
|
{
|
||||||
|
template<class Derived, class Value>
|
||||||
|
struct archetype
|
||||||
|
{
|
||||||
|
typedef void difference_type;
|
||||||
|
|
||||||
|
Derived& operator++();
|
||||||
|
Derived operator++(int) const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct traversal_archetype_impl<single_pass_traversal_tag>
|
||||||
|
{
|
||||||
|
template<class Derived, class Value>
|
||||||
|
struct archetype
|
||||||
|
: public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
|
||||||
|
public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Derived, class Value>
|
||||||
|
bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
||||||
|
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
// doesn't seem to pick up != from equality_comparable
|
||||||
|
template <class Derived, class Value>
|
||||||
|
bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
||||||
|
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
|
||||||
|
#endif
|
||||||
|
template <>
|
||||||
|
struct traversal_archetype_impl<forward_traversal_tag>
|
||||||
|
{
|
||||||
|
template<class Derived, class Value>
|
||||||
|
struct archetype
|
||||||
|
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
|
||||||
|
{
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct traversal_archetype_impl<bidirectional_traversal_tag>
|
||||||
|
{
|
||||||
|
template<class Derived, class Value>
|
||||||
|
struct archetype
|
||||||
|
: public traversal_archetype_<Derived, Value, forward_traversal_tag>
|
||||||
|
{
|
||||||
|
Derived& operator--();
|
||||||
|
Derived operator--(int) const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct traversal_archetype_impl<random_access_traversal_tag>
|
||||||
|
{
|
||||||
|
template<class Derived, class Value>
|
||||||
|
struct archetype
|
||||||
|
: public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >,
|
||||||
|
public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
|
||||||
|
{
|
||||||
|
Derived& operator+=(std::ptrdiff_t);
|
||||||
|
Derived& operator-=(std::ptrdiff_t);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Derived, class Value>
|
||||||
|
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||||
|
std::ptrdiff_t);
|
||||||
|
|
||||||
|
template <class Derived, class Value>
|
||||||
|
Derived& operator+(std::ptrdiff_t,
|
||||||
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||||
|
|
||||||
|
template <class Derived, class Value>
|
||||||
|
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||||
|
std::ptrdiff_t);
|
||||||
|
|
||||||
|
template <class Derived, class Value>
|
||||||
|
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||||
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||||
|
|
||||||
|
template <class Derived, class Value>
|
||||||
|
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||||
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||||
|
|
||||||
|
struct bogus_type;
|
||||||
|
|
||||||
|
template <class Value>
|
||||||
|
struct convertible_type
|
||||||
|
: mpl::if_< is_const<Value>,
|
||||||
|
typename remove_const<Value>::type,
|
||||||
|
bogus_type >
|
||||||
|
{};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
template <class> struct undefined;
|
||||||
|
|
||||||
|
template <class AccessCategory>
|
||||||
|
struct iterator_access_archetype_impl
|
||||||
|
{
|
||||||
|
template <class Value> struct archetype;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Value, class AccessCategory>
|
||||||
|
struct iterator_access_archetype
|
||||||
|
: mpl::aux::msvc_eti_base<
|
||||||
|
typename iterator_access_archetype_impl<
|
||||||
|
AccessCategory
|
||||||
|
>::template archetype<Value>
|
||||||
|
>::type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_access_archetype_impl<
|
||||||
|
iterator_archetypes::readable_iterator_t
|
||||||
|
>
|
||||||
|
{
|
||||||
|
template <class Value>
|
||||||
|
struct archetype
|
||||||
|
{
|
||||||
|
typedef typename remove_cv<Value>::type value_type;
|
||||||
|
typedef Value reference;
|
||||||
|
typedef Value* pointer;
|
||||||
|
|
||||||
|
value_type operator*() const;
|
||||||
|
|
||||||
|
detail::arrow_proxy<Value> operator->() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_access_archetype_impl<
|
||||||
|
iterator_archetypes::writable_iterator_t
|
||||||
|
>
|
||||||
|
{
|
||||||
|
template <class Value>
|
||||||
|
struct archetype
|
||||||
|
{
|
||||||
|
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
BOOST_STATIC_ASSERT(!is_const<Value>::value);
|
||||||
|
# endif
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void reference;
|
||||||
|
typedef void pointer;
|
||||||
|
|
||||||
|
detail::assign_proxy<Value> operator*() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_access_archetype_impl<
|
||||||
|
iterator_archetypes::readable_writable_iterator_t
|
||||||
|
>
|
||||||
|
{
|
||||||
|
template <class Value>
|
||||||
|
struct archetype
|
||||||
|
: public virtual iterator_access_archetype<
|
||||||
|
Value, iterator_archetypes::readable_iterator_t
|
||||||
|
>
|
||||||
|
{
|
||||||
|
typedef detail::read_write_proxy<Value> reference;
|
||||||
|
|
||||||
|
detail::read_write_proxy<Value> operator*() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_access_archetype_impl<iterator_archetypes::readable_lvalue_iterator_t>
|
||||||
|
{
|
||||||
|
template <class Value>
|
||||||
|
struct archetype
|
||||||
|
: public virtual iterator_access_archetype<
|
||||||
|
Value, iterator_archetypes::readable_iterator_t
|
||||||
|
>
|
||||||
|
{
|
||||||
|
typedef Value& reference;
|
||||||
|
|
||||||
|
Value& operator*() const;
|
||||||
|
Value* operator->() const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_access_archetype_impl<iterator_archetypes::writable_lvalue_iterator_t>
|
||||||
|
{
|
||||||
|
template <class Value>
|
||||||
|
struct archetype
|
||||||
|
: public virtual iterator_access_archetype<
|
||||||
|
Value, iterator_archetypes::readable_lvalue_iterator_t
|
||||||
|
>
|
||||||
|
{
|
||||||
|
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
BOOST_STATIC_ASSERT((!is_const<Value>::value));
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class Value, class AccessCategory, class TraversalCategory>
|
||||||
|
struct iterator_archetype;
|
||||||
|
|
||||||
|
template <class Value, class AccessCategory, class TraversalCategory>
|
||||||
|
struct traversal_archetype_base
|
||||||
|
: detail::operator_brackets<
|
||||||
|
typename remove_cv<Value>::type
|
||||||
|
, AccessCategory
|
||||||
|
, TraversalCategory
|
||||||
|
>
|
||||||
|
, detail::traversal_archetype_<
|
||||||
|
iterator_archetype<Value, AccessCategory, TraversalCategory>
|
||||||
|
, Value
|
||||||
|
, TraversalCategory
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class Value, class AccessCategory, class TraversalCategory>
|
||||||
|
struct iterator_archetype_base
|
||||||
|
: iterator_access_archetype<Value, AccessCategory>
|
||||||
|
, traversal_archetype_base<Value, AccessCategory, TraversalCategory>
|
||||||
|
{
|
||||||
|
typedef iterator_access_archetype<Value, AccessCategory> access;
|
||||||
|
|
||||||
|
typedef typename detail::facade_iterator_category<
|
||||||
|
TraversalCategory
|
||||||
|
, typename mpl::apply_if<
|
||||||
|
iterator_archetypes::has_access<
|
||||||
|
AccessCategory, iterator_archetypes::writable_iterator_t
|
||||||
|
>
|
||||||
|
, remove_const<Value>
|
||||||
|
, add_const<Value>
|
||||||
|
>::type
|
||||||
|
, typename access::reference
|
||||||
|
>::type iterator_category;
|
||||||
|
|
||||||
|
// Needed for some broken libraries (see below)
|
||||||
|
typedef boost::iterator<
|
||||||
|
iterator_category
|
||||||
|
, Value
|
||||||
|
, typename traversal_archetype_base<
|
||||||
|
Value, AccessCategory, TraversalCategory
|
||||||
|
>::difference_type
|
||||||
|
, typename access::pointer
|
||||||
|
, typename access::reference
|
||||||
|
> workaround_iterator_base;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Value, class AccessCategory, class TraversalCategory>
|
||||||
|
struct iterator_archetype
|
||||||
|
: public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory>
|
||||||
|
|
||||||
|
// These broken libraries require derivation from std::iterator
|
||||||
|
// (or related magic) in order to handle iter_swap and other
|
||||||
|
// iterator operations
|
||||||
|
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
||||||
|
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
||||||
|
, public detail::iterator_archetype_base<
|
||||||
|
Value, AccessCategory, TraversalCategory
|
||||||
|
>::workaround_iterator_base
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
// Derivation from std::iterator above caused references to nested
|
||||||
|
// types to be ambiguous, so now we have to redeclare them all
|
||||||
|
// here.
|
||||||
|
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
||||||
|
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
||||||
|
|
||||||
|
typedef detail::iterator_archetype_base<
|
||||||
|
Value,AccessCategory,TraversalCategory
|
||||||
|
> base;
|
||||||
|
|
||||||
|
typedef typename base::value_type value_type;
|
||||||
|
typedef typename base::reference reference;
|
||||||
|
typedef typename base::pointer pointer;
|
||||||
|
typedef typename base::difference_type difference_type;
|
||||||
|
typedef typename base::iterator_category iterator_category;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
iterator_archetype();
|
||||||
|
iterator_archetype(iterator_archetype const&);
|
||||||
|
|
||||||
|
iterator_archetype& operator=(iterator_archetype const&);
|
||||||
|
|
||||||
|
// Optional conversion from mutable
|
||||||
|
// iterator_archetype(iterator_archetype<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_ITERATOR_ARCHETYPES_HPP
|
165
include/boost/iterator/iterator_categories.hpp
Normal file
165
include/boost/iterator/iterator_categories.hpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
#ifndef BOOST_ITERATOR_CATEGORIES_HPP
|
||||||
|
# define BOOST_ITERATOR_CATEGORIES_HPP
|
||||||
|
|
||||||
|
# include <boost/config.hpp>
|
||||||
|
# include <boost/detail/iterator.hpp>
|
||||||
|
# include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
# include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
# include <boost/mpl/apply_if.hpp>
|
||||||
|
# include <boost/mpl/identity.hpp>
|
||||||
|
# include <boost/mpl/placeholders.hpp>
|
||||||
|
# include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
|
||||||
|
# include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
# include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Traversal Categories
|
||||||
|
//
|
||||||
|
struct incrementable_traversal_tag {};
|
||||||
|
|
||||||
|
struct single_pass_traversal_tag
|
||||||
|
: incrementable_traversal_tag {};
|
||||||
|
|
||||||
|
struct forward_traversal_tag
|
||||||
|
: single_pass_traversal_tag {};
|
||||||
|
|
||||||
|
struct bidirectional_traversal_tag
|
||||||
|
: forward_traversal_tag {};
|
||||||
|
|
||||||
|
struct random_access_traversal_tag
|
||||||
|
: bidirectional_traversal_tag {};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Convert a "strictly old-style" iterator category to a traversal
|
||||||
|
// tag. This is broken out into a separate metafunction to reduce
|
||||||
|
// the cost of instantiating iterator_category_to_traversal, below,
|
||||||
|
// for new-style types.
|
||||||
|
//
|
||||||
|
template <class Cat>
|
||||||
|
struct old_category_to_traversal
|
||||||
|
: mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::random_access_iterator_tag>
|
||||||
|
, mpl::identity<random_access_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::bidirectional_iterator_tag>
|
||||||
|
, mpl::identity<bidirectional_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::forward_iterator_tag>
|
||||||
|
, mpl::identity<forward_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::input_iterator_tag>
|
||||||
|
, mpl::identity<single_pass_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::output_iterator_tag>
|
||||||
|
, mpl::identity<incrementable_traversal_tag>
|
||||||
|
, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
template <>
|
||||||
|
struct old_category_to_traversal<int>
|
||||||
|
{
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
template <class Traversal>
|
||||||
|
struct pure_traversal_tag
|
||||||
|
: mpl::apply_if<
|
||||||
|
is_convertible<Traversal,random_access_traversal_tag>
|
||||||
|
, mpl::identity<random_access_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Traversal,bidirectional_traversal_tag>
|
||||||
|
, mpl::identity<bidirectional_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Traversal,forward_traversal_tag>
|
||||||
|
, mpl::identity<forward_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Traversal,single_pass_traversal_tag>
|
||||||
|
, mpl::identity<single_pass_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Traversal,incrementable_traversal_tag>
|
||||||
|
, mpl::identity<incrementable_traversal_tag>
|
||||||
|
, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
template <>
|
||||||
|
struct pure_traversal_tag<int>
|
||||||
|
{
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert an iterator category into a traversal tag
|
||||||
|
//
|
||||||
|
template <class Cat>
|
||||||
|
struct iterator_category_to_traversal
|
||||||
|
: mpl::apply_if< // if already convertible to a traversal tag, we're done.
|
||||||
|
is_convertible<Cat,incrementable_traversal_tag>
|
||||||
|
, mpl::identity<Cat>
|
||||||
|
, detail::old_category_to_traversal<Cat>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Trait to get an iterator's traversal category
|
||||||
|
template <class Iterator = mpl::_1>
|
||||||
|
struct iterator_traversal
|
||||||
|
: iterator_category_to_traversal<
|
||||||
|
typename boost::detail::iterator_traits<Iterator>::iterator_category
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
# ifdef BOOST_MPL_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_traversal<mpl::_1>
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct apply : iterator_traversal<T>
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct iterator_traversal<mpl::_>
|
||||||
|
: iterator_traversal<mpl::_1>
|
||||||
|
{};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_ITERATOR_CATEGORIES_HPP
|
379
include/boost/iterator/iterator_concepts.hpp
Normal file
379
include/boost/iterator/iterator_concepts.hpp
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
#ifndef BOOST_ITERATOR_CONCEPTS_HPP
|
||||||
|
#define BOOST_ITERATOR_CONCEPTS_HPP
|
||||||
|
|
||||||
|
// Revision History
|
||||||
|
// 26 Apr 2003 thw
|
||||||
|
// Adapted to new iterator concepts
|
||||||
|
// 22 Nov 2002 Thomas Witt
|
||||||
|
// Added interoperable concept.
|
||||||
|
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
|
||||||
|
// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems.
|
||||||
|
#include <boost/detail/iterator.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <boost/type_traits/is_integral.hpp>
|
||||||
|
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/mpl/if.hpp>
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/or.hpp>
|
||||||
|
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
// Use boost/limits to work around missing limits headers on some compilers
|
||||||
|
#include <boost/limits.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace boost_concepts {
|
||||||
|
// Used a different namespace here (instead of "boost") so that the
|
||||||
|
// concept descriptions do not take for granted the names in
|
||||||
|
// namespace boost.
|
||||||
|
|
||||||
|
// We use this in place of STATIC_ASSERT((is_convertible<...>))
|
||||||
|
// because some compilers (CWPro7.x) can't detect convertibility.
|
||||||
|
//
|
||||||
|
// Of course, that just gets us a different error at the moment with
|
||||||
|
// some tests, since new iterator category deduction still depends
|
||||||
|
// on convertibility detection. We might need some specializations
|
||||||
|
// to support this compiler.
|
||||||
|
template <class Target, class Source>
|
||||||
|
struct static_assert_base_and_derived
|
||||||
|
{
|
||||||
|
static_assert_base_and_derived(Target* = (Source*)0) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Iterator Access Concepts
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class ReadableIteratorConcept {
|
||||||
|
public:
|
||||||
|
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::reference reference;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||||
|
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost::DefaultConstructibleConcept<Iterator> >();
|
||||||
|
|
||||||
|
reference r = *i; // or perhaps read(x)
|
||||||
|
value_type v(r);
|
||||||
|
boost::ignore_unused_variable_warning(v);
|
||||||
|
}
|
||||||
|
Iterator i;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename Iterator
|
||||||
|
, typename ValueType = typename boost::detail::iterator_traits<Iterator>::value_type
|
||||||
|
>
|
||||||
|
class WritableIteratorConcept {
|
||||||
|
public:
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||||
|
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost::DefaultConstructibleConcept<Iterator> >();
|
||||||
|
|
||||||
|
*i = v; // a good alternative could be something like write(x, v)
|
||||||
|
}
|
||||||
|
ValueType v;
|
||||||
|
Iterator i;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class SwappableIteratorConcept {
|
||||||
|
public:
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
std::iter_swap(i1, i2);
|
||||||
|
}
|
||||||
|
Iterator i1;
|
||||||
|
Iterator i2;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class ReadableLvalueIteratorConcept
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||||
|
|
||||||
|
void constraints()
|
||||||
|
{
|
||||||
|
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
||||||
|
|
||||||
|
typedef boost::mpl::or_<
|
||||||
|
boost::is_same<reference, value_type&>
|
||||||
|
, boost::is_same<reference, value_type const&>
|
||||||
|
> correct_reference;
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(correct_reference::value);
|
||||||
|
|
||||||
|
reference v = *i;
|
||||||
|
boost::ignore_unused_variable_warning(v);
|
||||||
|
}
|
||||||
|
Iterator i;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class WritableLvalueIteratorConcept {
|
||||||
|
public:
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires<
|
||||||
|
ReadableLvalueIteratorConcept<Iterator> >();
|
||||||
|
boost::function_requires<
|
||||||
|
WritableIteratorConcept<Iterator, value_type> >();
|
||||||
|
boost::function_requires<
|
||||||
|
SwappableIteratorConcept<Iterator> >();
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Iterator Traversal Concepts
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class IncrementableIteratorConcept {
|
||||||
|
public:
|
||||||
|
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost::DefaultConstructibleConcept<Iterator> >();
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
(boost::is_convertible<
|
||||||
|
traversal_category
|
||||||
|
, boost::incrementable_traversal_tag
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
++i;
|
||||||
|
(void)i++;
|
||||||
|
}
|
||||||
|
Iterator i;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class SinglePassIteratorConcept {
|
||||||
|
public:
|
||||||
|
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< IncrementableIteratorConcept<Iterator> >();
|
||||||
|
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
(boost::is_convertible<
|
||||||
|
traversal_category
|
||||||
|
, boost::single_pass_traversal_tag
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class ForwardTraversalConcept {
|
||||||
|
public:
|
||||||
|
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< SinglePassIteratorConcept<Iterator> >();
|
||||||
|
|
||||||
|
typedef boost::mpl::and_<
|
||||||
|
boost::is_integral<difference_type>,
|
||||||
|
boost::mpl::bool_< std::numeric_limits<difference_type>::is_signed >
|
||||||
|
> difference_type_is_signed_integral;
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
(boost::is_convertible<
|
||||||
|
traversal_category
|
||||||
|
, boost::forward_traversal_tag
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class BidirectionalTraversalConcept {
|
||||||
|
public:
|
||||||
|
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< ForwardTraversalConcept<Iterator> >();
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
(boost::is_convertible<
|
||||||
|
traversal_category
|
||||||
|
, boost::bidirectional_traversal_tag
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
--i;
|
||||||
|
(void)i--;
|
||||||
|
}
|
||||||
|
Iterator i;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
class RandomAccessTraversalConcept {
|
||||||
|
public:
|
||||||
|
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::difference_type
|
||||||
|
difference_type;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
boost::function_requires< BidirectionalTraversalConcept<Iterator> >();
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
(boost::is_convertible<
|
||||||
|
traversal_category
|
||||||
|
, boost::random_access_traversal_tag
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
i += n;
|
||||||
|
i = i + n;
|
||||||
|
i = n + i;
|
||||||
|
i -= n;
|
||||||
|
i = i - n;
|
||||||
|
n = i - j;
|
||||||
|
}
|
||||||
|
difference_type n;
|
||||||
|
Iterator i, j;
|
||||||
|
};
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Iterator Interoperability Concept
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename TraversalTag>
|
||||||
|
struct Operations;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Operations<boost::incrementable_traversal_tag>
|
||||||
|
{
|
||||||
|
template <typename Iterator1, typename Iterator2>
|
||||||
|
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||||
|
{
|
||||||
|
// no interoperability constraints
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Operations<boost::single_pass_traversal_tag>
|
||||||
|
{
|
||||||
|
template <typename Iterator1, typename Iterator2>
|
||||||
|
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||||
|
{
|
||||||
|
Operations<boost::incrementable_traversal_tag>::constraints(i1, i2);
|
||||||
|
i1 == i2;
|
||||||
|
i1 != i2;
|
||||||
|
|
||||||
|
i2 == i1;
|
||||||
|
i2 != i1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Operations<boost::forward_traversal_tag>
|
||||||
|
{
|
||||||
|
template <typename Iterator1, typename Iterator2>
|
||||||
|
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||||
|
{
|
||||||
|
Operations<boost::single_pass_traversal_tag>::constraints(i1, i2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Operations<boost::bidirectional_traversal_tag>
|
||||||
|
{
|
||||||
|
template <typename Iterator1, typename Iterator2>
|
||||||
|
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||||
|
{
|
||||||
|
Operations<boost::forward_traversal_tag>::constraints(i1, i2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Operations<boost::random_access_traversal_tag>
|
||||||
|
{
|
||||||
|
template <typename Iterator1, typename Iterator2>
|
||||||
|
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||||
|
{
|
||||||
|
Operations<boost::bidirectional_traversal_tag>::constraints(i1, i2);
|
||||||
|
|
||||||
|
i1 < i2;
|
||||||
|
i1 <= i2;
|
||||||
|
i1 > i2;
|
||||||
|
i1 >= i2;
|
||||||
|
i1 - i2;
|
||||||
|
|
||||||
|
i2 < i1;
|
||||||
|
i2 <= i1;
|
||||||
|
i2 > i1;
|
||||||
|
i2 >= i1;
|
||||||
|
i2 - i1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename Iterator, typename ConstIterator>
|
||||||
|
class InteroperableConcept
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||||
|
typedef typename boost::detail::iterator_traits<Iterator>::difference_type
|
||||||
|
difference_type;
|
||||||
|
|
||||||
|
typedef typename boost::iterator_traversal<ConstIterator>::type
|
||||||
|
const_traversal_category;
|
||||||
|
typedef typename boost::detail::iterator_traits<ConstIterator>::difference_type
|
||||||
|
const_difference_type;
|
||||||
|
|
||||||
|
void constraints() {
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same< difference_type,
|
||||||
|
const_difference_type>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same< traversal_category,
|
||||||
|
const_traversal_category>::value));
|
||||||
|
|
||||||
|
// ToDo check what the std really requires
|
||||||
|
|
||||||
|
// detail::Operations<traversal_category>::constraints(i, ci);
|
||||||
|
|
||||||
|
ci = i;
|
||||||
|
|
||||||
|
}
|
||||||
|
Iterator i;
|
||||||
|
ConstIterator ci;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace boost_concepts
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_ITERATOR_CONCEPTS_HPP
|
589
include/boost/iterator/iterator_facade.hpp
Normal file
589
include/boost/iterator/iterator_facade.hpp
Normal file
@ -0,0 +1,589 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP
|
||||||
|
#define BOOST_ITERATOR_FACADE_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/iterator/interoperable.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/facade_iterator_category.hpp>
|
||||||
|
#include <boost/iterator/detail/enable_if.hpp>
|
||||||
|
|
||||||
|
#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/remove_const.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
#include <boost/mpl/apply_if.hpp>
|
||||||
|
#include <boost/mpl/or.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_def.hpp> // this goes last
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
// This forward declaration is required for the friend declaration
|
||||||
|
// in iterator_core_access
|
||||||
|
template <class I, class V, class TC, class R, class D> class iterator_facade;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// enable if for use in operator implementation.
|
||||||
|
//
|
||||||
|
// enable_if_interoperable falls back to always enabled for compilers
|
||||||
|
// that don't support enable_if or is_convertible.
|
||||||
|
//
|
||||||
|
template <
|
||||||
|
class Facade1
|
||||||
|
, class Facade2
|
||||||
|
, class Return
|
||||||
|
>
|
||||||
|
struct enable_if_interoperable
|
||||||
|
#ifndef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||||
|
: ::boost::iterators::enable_if<
|
||||||
|
mpl::or_<
|
||||||
|
is_convertible<Facade1, Facade2>
|
||||||
|
, is_convertible<Facade2, Facade1>
|
||||||
|
>
|
||||||
|
, Return
|
||||||
|
>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||||
|
typedef Return type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generates associated types for an iterator_facade with the
|
||||||
|
// given parameters.
|
||||||
|
//
|
||||||
|
template <
|
||||||
|
class ValueParam
|
||||||
|
, class CategoryOrTraversal
|
||||||
|
, class Reference
|
||||||
|
, class Difference
|
||||||
|
>
|
||||||
|
struct iterator_facade_types
|
||||||
|
{
|
||||||
|
typedef typename facade_iterator_category<
|
||||||
|
CategoryOrTraversal, ValueParam, Reference
|
||||||
|
>::type iterator_category;
|
||||||
|
|
||||||
|
typedef typename remove_const<ValueParam>::type value_type;
|
||||||
|
|
||||||
|
typedef typename mpl::apply_if<
|
||||||
|
detail::iterator_writability_disabled<ValueParam,Reference>
|
||||||
|
, add_pointer<typename add_const<value_type>::type>
|
||||||
|
, add_pointer<value_type>
|
||||||
|
>::type pointer;
|
||||||
|
|
||||||
|
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
||||||
|
&& (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
|
||||||
|
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
|
||||||
|
|| BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
|
||||||
|
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
|
||||||
|
|
||||||
|
// To interoperate with some broken library/compiler
|
||||||
|
// combinations, user-defined iterators must be derived from
|
||||||
|
// std::iterator. It is possible to implement a standard
|
||||||
|
// library for broken compilers without this limitation.
|
||||||
|
# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
|
||||||
|
|
||||||
|
typedef
|
||||||
|
iterator<iterator_category, value_type, Difference, pointer, Reference>
|
||||||
|
base;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// operator->() needs special support for input iterators to strictly meet the
|
||||||
|
// standard's requirements. If *i is not a reference type, we must still
|
||||||
|
// produce a (constant) lvalue to which a pointer can be formed. We do that by
|
||||||
|
// returning an instantiation of this special proxy class template.
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct operator_arrow_proxy
|
||||||
|
{
|
||||||
|
operator_arrow_proxy(T const* px) : m_value(*px) {}
|
||||||
|
const T* operator->() const { return &m_value; }
|
||||||
|
// This function is needed for MWCW and BCC, which won't call operator->
|
||||||
|
// again automatically per 13.3.1.2 para 8
|
||||||
|
operator const T*() const { return &m_value; }
|
||||||
|
T m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A metafunction that gets the result type for operator->. Also
|
||||||
|
// has a static function make() which builds the result from a
|
||||||
|
// Reference
|
||||||
|
template <class Value, class Reference, class Pointer>
|
||||||
|
struct operator_arrow_result
|
||||||
|
{
|
||||||
|
// CWPro8.3 won't accept "operator_arrow_result::type", and we
|
||||||
|
// need that type below, so metafunction forwarding would be a
|
||||||
|
// losing proposition here.
|
||||||
|
typedef typename mpl::if_<
|
||||||
|
is_reference<Reference>
|
||||||
|
, Pointer
|
||||||
|
, operator_arrow_proxy<Value>
|
||||||
|
>::type type;
|
||||||
|
|
||||||
|
static type make(Reference x)
|
||||||
|
{
|
||||||
|
return type(&x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||||
|
// Deal with ETI
|
||||||
|
template<>
|
||||||
|
struct operator_arrow_result<int, int, int>
|
||||||
|
{
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Iterator is actually an iterator_facade, so we do not have to
|
||||||
|
// go through iterator_traits to access the traits.
|
||||||
|
//
|
||||||
|
template <class Iterator>
|
||||||
|
class operator_brackets_proxy
|
||||||
|
{
|
||||||
|
typedef typename Iterator::reference reference;
|
||||||
|
typedef typename Iterator::value_type value_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
operator_brackets_proxy(Iterator const& iter)
|
||||||
|
: m_iter(iter)
|
||||||
|
{}
|
||||||
|
|
||||||
|
operator reference() const
|
||||||
|
{
|
||||||
|
return *m_iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator_brackets_proxy& operator=(value_type const& val)
|
||||||
|
{
|
||||||
|
*m_iter = val;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator m_iter;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iterator, class Value, class Reference>
|
||||||
|
struct operator_brackets_result
|
||||||
|
{
|
||||||
|
typedef typename mpl::if_<
|
||||||
|
iterator_writability_disabled<Value,Reference>
|
||||||
|
, Value
|
||||||
|
, operator_brackets_proxy<Iterator>
|
||||||
|
>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::false_)
|
||||||
|
{
|
||||||
|
return operator_brackets_proxy<Iterator>(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::true_)
|
||||||
|
{
|
||||||
|
return *iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
// Macros which describe the declarations of binary operators
|
||||||
|
# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
|
||||||
|
template < \
|
||||||
|
class Derived1, class V1, class TC1, class R1, class D1 \
|
||||||
|
, class Derived2, class V2, class TC2, class R2, class D2 \
|
||||||
|
> \
|
||||||
|
prefix typename detail::enable_if_interoperable< \
|
||||||
|
Derived1, Derived2, result_type \
|
||||||
|
>::type \
|
||||||
|
operator op( \
|
||||||
|
iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \
|
||||||
|
, iterator_facade<Derived2, V2, TC2, R2, D2> const& rhs)
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
|
||||||
|
template <class Derived, class V, class TC, class R, class D> \
|
||||||
|
prefix Derived operator+ args
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper class for granting access to the iterator core interface.
|
||||||
|
//
|
||||||
|
// The simple core interface is used by iterator_facade. The core
|
||||||
|
// interface of a user/library defined iterator type should not be made public
|
||||||
|
// so that it does not clutter the public interface. Instead iterator_core_access
|
||||||
|
// should be made friend so that iterator_facade can access the core
|
||||||
|
// interface through iterator_core_access.
|
||||||
|
//
|
||||||
|
class iterator_core_access
|
||||||
|
{
|
||||||
|
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
|
||||||
|
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
// Tasteless as this may seem, making all members public allows member templates
|
||||||
|
// to work in the absence of member template friends.
|
||||||
|
public:
|
||||||
|
# else
|
||||||
|
|
||||||
|
template <class I, class V, class TC, class R, class D> friend class iterator_facade;
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_FACADE_RELATION(op) \
|
||||||
|
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool);
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(==)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(!=)
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(<)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(>)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(<=)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(>=)
|
||||||
|
# undef BOOST_ITERATOR_FACADE_RELATION
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_INTEROP_HEAD(
|
||||||
|
friend, -, typename Derived1::difference_type)
|
||||||
|
;
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
||||||
|
friend
|
||||||
|
, (iterator_facade<Derived, V, TC, R, D> const&
|
||||||
|
, typename Derived::difference_type)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
||||||
|
friend
|
||||||
|
, (typename Derived::difference_type
|
||||||
|
, iterator_facade<Derived, V, TC, R, D> const&)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
template <class Facade>
|
||||||
|
static typename Facade::reference dereference(Facade const& f)
|
||||||
|
{
|
||||||
|
return f.dereference();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Facade>
|
||||||
|
static void increment(Facade& f)
|
||||||
|
{
|
||||||
|
f.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Facade>
|
||||||
|
static void decrement(Facade& f)
|
||||||
|
{
|
||||||
|
f.decrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Facade1, class Facade2>
|
||||||
|
static bool equal(Facade1 const& f1, Facade2 const& f2)
|
||||||
|
{
|
||||||
|
return f1.equal(f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Facade>
|
||||||
|
static void advance(Facade& f, typename Facade::difference_type n)
|
||||||
|
{
|
||||||
|
f.advance(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Facade1, class Facade2>
|
||||||
|
static typename Facade1::difference_type distance_to(
|
||||||
|
Facade1 const& f1, Facade2 const& f2)
|
||||||
|
{
|
||||||
|
return f1.distance_to(f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// objects of this class are useless
|
||||||
|
iterator_core_access(); //undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterator_facade - use as a public base class for defining new
|
||||||
|
// standard-conforming iterators.
|
||||||
|
//
|
||||||
|
template <
|
||||||
|
class Derived // The derived iterator type being constructed
|
||||||
|
, class Value
|
||||||
|
, class CategoryOrTraversal
|
||||||
|
, class Reference = Value&
|
||||||
|
, class Difference = std::ptrdiff_t
|
||||||
|
>
|
||||||
|
class iterator_facade
|
||||||
|
# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
||||||
|
: public detail::iterator_facade_types<
|
||||||
|
Value, CategoryOrTraversal, Reference, Difference
|
||||||
|
>::base
|
||||||
|
# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//
|
||||||
|
// Curiously Recurring Template interface.
|
||||||
|
//
|
||||||
|
typedef Derived derived_t;
|
||||||
|
|
||||||
|
Derived& derived()
|
||||||
|
{
|
||||||
|
return static_cast<Derived&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived const& derived() const
|
||||||
|
{
|
||||||
|
return static_cast<Derived const&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef detail::iterator_facade_types<
|
||||||
|
Value, CategoryOrTraversal, Reference, Difference
|
||||||
|
> associated_types;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef typename associated_types::value_type value_type;
|
||||||
|
typedef Reference reference;
|
||||||
|
typedef Difference difference_type;
|
||||||
|
typedef typename associated_types::pointer pointer;
|
||||||
|
typedef typename associated_types::iterator_category iterator_category;
|
||||||
|
|
||||||
|
reference operator*() const
|
||||||
|
{
|
||||||
|
return iterator_core_access::dereference(this->derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
typename detail::operator_arrow_result<
|
||||||
|
value_type
|
||||||
|
, reference
|
||||||
|
, pointer
|
||||||
|
>::type
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
return detail::operator_arrow_result<
|
||||||
|
value_type
|
||||||
|
, reference
|
||||||
|
, pointer
|
||||||
|
>::make(*this->derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
typename detail::operator_brackets_result<Derived,Value,Reference>::type
|
||||||
|
operator[](difference_type n) const
|
||||||
|
{
|
||||||
|
typedef detail::iterator_writability_disabled<Value,Reference>
|
||||||
|
not_writable;
|
||||||
|
|
||||||
|
return detail::make_operator_brackets_result<Derived>(
|
||||||
|
this->derived() + n
|
||||||
|
, not_writable()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived& operator++()
|
||||||
|
{
|
||||||
|
iterator_core_access::increment(this->derived());
|
||||||
|
return this->derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived operator++(int)
|
||||||
|
{
|
||||||
|
Derived tmp(this->derived());
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived& operator--()
|
||||||
|
{
|
||||||
|
iterator_core_access::decrement(this->derived());
|
||||||
|
return this->derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived operator--(int)
|
||||||
|
{
|
||||||
|
Derived tmp(this->derived());
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived& operator+=(difference_type n)
|
||||||
|
{
|
||||||
|
iterator_core_access::advance(this->derived(), n);
|
||||||
|
return this->derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived& operator-=(difference_type n)
|
||||||
|
{
|
||||||
|
iterator_core_access::advance(this->derived(), -n);
|
||||||
|
return this->derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived operator-(difference_type x) const
|
||||||
|
{
|
||||||
|
Derived result(this->derived());
|
||||||
|
return result -= x;
|
||||||
|
}
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||||
|
// There appears to be a bug which trashes the data of classes
|
||||||
|
// derived from iterator_facade when they are assigned unless we
|
||||||
|
// define this assignment operator. This bug is only revealed
|
||||||
|
// (so far) in STLPort debug mode, but it's clearly a codegen
|
||||||
|
// problem so we apply the workaround for all MSVC6.
|
||||||
|
iterator_facade& operator=(iterator_facade const&)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Operator implementation. The library supplied operators
|
||||||
|
// enables the user to provide fully interoperable constant/mutable
|
||||||
|
// iterator types. I.e. the library provides all operators
|
||||||
|
// for all mutable/constant iterator combinations.
|
||||||
|
//
|
||||||
|
// Note though that this kind of interoperability for constant/mutable
|
||||||
|
// iterators is not required by the standard for container iterators.
|
||||||
|
// All the standard asks for is a conversion mutable -> constant.
|
||||||
|
// Most standard library implementations nowadays provide fully interoperable
|
||||||
|
// iterator implementations, but there are still heavily used implementations
|
||||||
|
// that do not provide them. (Actually it's even worse, they do not provide
|
||||||
|
// them for only a few iterators.)
|
||||||
|
//
|
||||||
|
// ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
|
||||||
|
// enable the user to turn off mixed type operators
|
||||||
|
//
|
||||||
|
// The library takes care to provide only the right operator overloads.
|
||||||
|
// I.e.
|
||||||
|
//
|
||||||
|
// bool operator==(Iterator, Iterator);
|
||||||
|
// bool operator==(ConstIterator, Iterator);
|
||||||
|
// bool operator==(Iterator, ConstIterator);
|
||||||
|
// bool operator==(ConstIterator, ConstIterator);
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// In order to do so it uses c++ idioms that are not yet widely supported
|
||||||
|
// by current compiler releases. The library is designed to degrade gracefully
|
||||||
|
// in the face of compiler deficiencies. In general compiler
|
||||||
|
// deficiencies result in less strict error checking and more obscure
|
||||||
|
// error messages, functionality is not affected.
|
||||||
|
//
|
||||||
|
// For full operation compiler support for "Substitution Failure Is Not An Error"
|
||||||
|
// (aka. enable_if) and boost::is_convertible is required.
|
||||||
|
//
|
||||||
|
// The following problems occur if support is lacking.
|
||||||
|
//
|
||||||
|
// Pseudo code
|
||||||
|
//
|
||||||
|
// ---------------
|
||||||
|
// AdaptorA<Iterator1> a1;
|
||||||
|
// AdaptorA<Iterator2> a2;
|
||||||
|
//
|
||||||
|
// // This will result in a no such overload error in full operation
|
||||||
|
// // If enable_if or is_convertible is not supported
|
||||||
|
// // The instantiation will fail with an error hopefully indicating that
|
||||||
|
// // there is no operator== for Iterator1, Iterator2
|
||||||
|
// // The same will happen if no enable_if is used to remove
|
||||||
|
// // false overloads from the templated conversion constructor
|
||||||
|
// // of AdaptorA.
|
||||||
|
//
|
||||||
|
// a1 == a2;
|
||||||
|
// ----------------
|
||||||
|
//
|
||||||
|
// AdaptorA<Iterator> a;
|
||||||
|
// AdaptorB<Iterator> b;
|
||||||
|
//
|
||||||
|
// // This will result in a no such overload error in full operation
|
||||||
|
// // If enable_if is not supported the static assert used
|
||||||
|
// // in the operator implementation will fail.
|
||||||
|
// // This will accidently work if is_convertible is not supported.
|
||||||
|
//
|
||||||
|
// a == b;
|
||||||
|
// ----------------
|
||||||
|
//
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, condition, return_prefix, base_op) \
|
||||||
|
BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
|
||||||
|
{ \
|
||||||
|
/* For those compilers that do not support enable_if */ \
|
||||||
|
BOOST_STATIC_ASSERT(( \
|
||||||
|
is_interoperable< Derived1, Derived2 >::value \
|
||||||
|
&& condition \
|
||||||
|
)); \
|
||||||
|
return_prefix iterator_core_access::base_op( \
|
||||||
|
static_cast<Derived2 const&>(rhs), static_cast<Derived1 const&>(lhs)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
|
||||||
|
BOOST_ITERATOR_FACADE_INTEROP( \
|
||||||
|
op \
|
||||||
|
, bool \
|
||||||
|
, true \
|
||||||
|
, return_prefix \
|
||||||
|
, base_op \
|
||||||
|
)
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal)
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_to)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_to)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_to)
|
||||||
|
BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_to)
|
||||||
|
# undef BOOST_ITERATOR_FACADE_RELATION
|
||||||
|
|
||||||
|
// operator- requires an additional part in the static assertion
|
||||||
|
BOOST_ITERATOR_FACADE_INTEROP(
|
||||||
|
-
|
||||||
|
, typename Derived1::difference_type
|
||||||
|
, (is_same<
|
||||||
|
BOOST_DEDUCED_TYPENAME Derived1::difference_type
|
||||||
|
, BOOST_DEDUCED_TYPENAME Derived2::difference_type
|
||||||
|
>::value)
|
||||||
|
, return
|
||||||
|
, distance_to )
|
||||||
|
# undef BOOST_ITERATOR_FACADE_INTEROP
|
||||||
|
# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
|
||||||
|
|
||||||
|
# define BOOST_ITERATOR_FACADE_PLUS(args) \
|
||||||
|
BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
|
||||||
|
{ \
|
||||||
|
Derived tmp(static_cast<Derived const&>(i)); \
|
||||||
|
return tmp += n; \
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_PLUS((
|
||||||
|
iterator_facade<Derived, V, TC, R, D> const& i
|
||||||
|
, typename Derived::difference_type n
|
||||||
|
))
|
||||||
|
|
||||||
|
BOOST_ITERATOR_FACADE_PLUS((
|
||||||
|
typename Derived::difference_type n
|
||||||
|
, iterator_facade<Derived, V, TC, R, D> const& i
|
||||||
|
))
|
||||||
|
# undef BOOST_ITERATOR_FACADE_PLUS
|
||||||
|
# undef BOOST_ITERATOR_FACADE_PLUS_HEAD
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP
|
93
include/boost/iterator/iterator_traits.hpp
Normal file
93
include/boost/iterator/iterator_traits.hpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef ITERATOR_TRAITS_DWA200347_HPP
|
||||||
|
# define ITERATOR_TRAITS_DWA200347_HPP
|
||||||
|
|
||||||
|
# include <boost/detail/iterator.hpp>
|
||||||
|
# include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
// Unfortunately, g++ 2.95.x chokes when we define a class template
|
||||||
|
// iterator_category which has the same name as its
|
||||||
|
// std::iterator_category() function, probably due in part to the
|
||||||
|
// "std:: is visible globally" hack it uses. Use
|
||||||
|
// BOOST_ITERATOR_CATEGORY to write code that's portable to older
|
||||||
|
// GCCs.
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(__GNUC__, <= 2)
|
||||||
|
# define BOOST_ITERATOR_CATEGORY iterator_category_
|
||||||
|
# else
|
||||||
|
# define BOOST_ITERATOR_CATEGORY iterator_category
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
struct iterator_value
|
||||||
|
{
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::value_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
struct iterator_reference
|
||||||
|
{
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::reference type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
struct iterator_pointer
|
||||||
|
{
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::pointer type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
struct iterator_difference
|
||||||
|
{
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::difference_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
struct BOOST_ITERATOR_CATEGORY
|
||||||
|
{
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::iterator_category type;
|
||||||
|
};
|
||||||
|
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||||
|
template <>
|
||||||
|
struct iterator_value<int>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_reference<int>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_pointer<int>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_difference<int>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct BOOST_ITERATOR_CATEGORY<int>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
} // namespace boost::iterator
|
||||||
|
|
||||||
|
#endif // ITERATOR_TRAITS_DWA200347_HPP
|
214
include/boost/iterator/new_iterator_tests.hpp
Normal file
214
include/boost/iterator/new_iterator_tests.hpp
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
#ifndef BOOST_NEW_ITERATOR_TESTS_HPP
|
||||||
|
# define BOOST_NEW_ITERATOR_TESTS_HPP
|
||||||
|
|
||||||
|
// This is meant to be the beginnings of a comprehensive, generic
|
||||||
|
// test suite for STL concepts such as iterators and containers.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
// 28 Oct 2002 Started update for new iterator categories
|
||||||
|
// (Jeremy Siek)
|
||||||
|
// 28 Apr 2002 Fixed input iterator requirements.
|
||||||
|
// For a == b a++ == b++ is no longer required.
|
||||||
|
// See 24.1.1/3 for details.
|
||||||
|
// (Thomas Witt)
|
||||||
|
// 08 Feb 2001 Fixed bidirectional iterator test so that
|
||||||
|
// --i is no longer a precondition.
|
||||||
|
// (Jeremy Siek)
|
||||||
|
// 04 Feb 2001 Added lvalue test, corrected preconditions
|
||||||
|
// (David Abrahams)
|
||||||
|
|
||||||
|
# include <iterator>
|
||||||
|
# include <assert.h>
|
||||||
|
# include <boost/type_traits.hpp>
|
||||||
|
# include <boost/static_assert.hpp>
|
||||||
|
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor
|
||||||
|
# include <boost/detail/iterator.hpp>
|
||||||
|
# include <boost/pending/iterator_tests.hpp>
|
||||||
|
# include <boost/iterator/is_readable_iterator.hpp>
|
||||||
|
# include <boost/iterator/is_lvalue_iterator.hpp>
|
||||||
|
|
||||||
|
# include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
// Preconditions: *i == v
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void readable_iterator_test(const Iterator i1, T v)
|
||||||
|
{
|
||||||
|
Iterator i2(i1); // Copy Constructible
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::reference ref_t;
|
||||||
|
ref_t r1 = *i1;
|
||||||
|
ref_t r2 = *i2;
|
||||||
|
T v1 = r1;
|
||||||
|
T v2 = r2;
|
||||||
|
assert(v1 == v);
|
||||||
|
assert(v2 == v);
|
||||||
|
|
||||||
|
# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
// I think we don't really need this as it checks the same things as
|
||||||
|
// the above code.
|
||||||
|
BOOST_STATIC_ASSERT(is_readable_iterator<Iterator>::value);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void writable_iterator_test(Iterator i, T v)
|
||||||
|
{
|
||||||
|
Iterator i2(i); // Copy Constructible
|
||||||
|
*i2 = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator>
|
||||||
|
void swappable_iterator_test(Iterator i, Iterator j)
|
||||||
|
{
|
||||||
|
Iterator i2(i), j2(j);
|
||||||
|
typename detail::iterator_traits<Iterator>::value_type bi = *i, bj = *j;
|
||||||
|
iter_swap(i2, j2);
|
||||||
|
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
|
||||||
|
assert(bi == aj && bj == ai);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void constant_lvalue_iterator_test(Iterator i, T v1)
|
||||||
|
{
|
||||||
|
Iterator i2(i);
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::reference reference;
|
||||||
|
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
|
||||||
|
const T& v2 = *i2;
|
||||||
|
assert(v1 == v2);
|
||||||
|
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator<Iterator>::value);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void non_const_lvalue_iterator_test(Iterator i, T v1, T v2)
|
||||||
|
{
|
||||||
|
Iterator i2(i);
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef typename detail::iterator_traits<Iterator>::reference reference;
|
||||||
|
BOOST_STATIC_ASSERT((is_same<value_type&, reference>::value));
|
||||||
|
T& v3 = *i2;
|
||||||
|
assert(v1 == v3);
|
||||||
|
|
||||||
|
// A non-const lvalue iterator is not neccessarily writable, but we
|
||||||
|
// are assuming the value_type is assignable here
|
||||||
|
*i = v2;
|
||||||
|
|
||||||
|
T& v4 = *i2;
|
||||||
|
assert(v2 == v4);
|
||||||
|
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator<Iterator>::value);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2)
|
||||||
|
{
|
||||||
|
Iterator i2;
|
||||||
|
Iterator i3(i);
|
||||||
|
i2 = i;
|
||||||
|
assert(i2 == i3);
|
||||||
|
assert(i != j);
|
||||||
|
assert(i2 != j);
|
||||||
|
readable_iterator_test(i, val1);
|
||||||
|
readable_iterator_test(i2, val1);
|
||||||
|
readable_iterator_test(i3, val1);
|
||||||
|
|
||||||
|
assert(i == i2++);
|
||||||
|
assert(i != ++i3);
|
||||||
|
|
||||||
|
readable_iterator_test(i2, val2);
|
||||||
|
readable_iterator_test(i3, val2);
|
||||||
|
|
||||||
|
readable_iterator_test(i, val1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2)
|
||||||
|
{
|
||||||
|
forward_readable_iterator_test(i, j, val1, val2);
|
||||||
|
Iterator i2 = i;
|
||||||
|
++i2;
|
||||||
|
swappable_iterator_test(i, i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bidirectional
|
||||||
|
// Preconditions: *i == v1, *++i == v2
|
||||||
|
template <class Iterator, class T>
|
||||||
|
void bidirectional_readable_iterator_test(Iterator i, T v1, T v2)
|
||||||
|
{
|
||||||
|
Iterator j(i);
|
||||||
|
++j;
|
||||||
|
forward_readable_iterator_test(i, j, v1, v2);
|
||||||
|
++i;
|
||||||
|
|
||||||
|
Iterator i1 = i, i2 = i;
|
||||||
|
|
||||||
|
assert(i == i1--);
|
||||||
|
assert(i != --i2);
|
||||||
|
|
||||||
|
readable_iterator_test(i, v2);
|
||||||
|
readable_iterator_test(i1, v1);
|
||||||
|
readable_iterator_test(i2, v1);
|
||||||
|
|
||||||
|
--i;
|
||||||
|
assert(i == i1);
|
||||||
|
assert(i == i2);
|
||||||
|
++i1;
|
||||||
|
++i2;
|
||||||
|
|
||||||
|
readable_iterator_test(i, v1);
|
||||||
|
readable_iterator_test(i1, v2);
|
||||||
|
readable_iterator_test(i2, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// random access
|
||||||
|
// Preconditions: [i,i+N) is a valid range
|
||||||
|
template <class Iterator, class TrueVals>
|
||||||
|
void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
|
||||||
|
{
|
||||||
|
bidirectional_readable_iterator_test(i, vals[0], vals[1]);
|
||||||
|
const Iterator j = i;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < N-1; ++c)
|
||||||
|
{
|
||||||
|
assert(i == j + c);
|
||||||
|
assert(*i == vals[c]);
|
||||||
|
typename detail::iterator_traits<Iterator>::value_type x = j[c];
|
||||||
|
assert(*i == x);
|
||||||
|
assert(*i == *(j + c));
|
||||||
|
assert(*i == *(c + j));
|
||||||
|
++i;
|
||||||
|
assert(i > j);
|
||||||
|
assert(i >= j);
|
||||||
|
assert(j <= i);
|
||||||
|
assert(j < i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator k = j + N - 1;
|
||||||
|
for (c = 0; c < N-1; ++c)
|
||||||
|
{
|
||||||
|
assert(i == k - c);
|
||||||
|
assert(*i == vals[N - 1 - c]);
|
||||||
|
typename detail::iterator_traits<Iterator>::value_type x = j[N - 1 - c];
|
||||||
|
assert(*i == x);
|
||||||
|
Iterator q = k - c;
|
||||||
|
assert(*i == *q);
|
||||||
|
assert(i > j);
|
||||||
|
assert(i >= j);
|
||||||
|
assert(j <= i);
|
||||||
|
assert(j < i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
# include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_NEW_ITERATOR_TESTS_HPP
|
92
include/boost/iterator/permutation_iterator.hpp
Normal file
92
include/boost/iterator/permutation_iterator.hpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// (C) Copyright Toon Knapen 2001.
|
||||||
|
// (C) Copyright David Abrahams 2003.
|
||||||
|
// (C) Copyright Roland Richter 2003.
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
|
#ifndef BOOST_PERMUTATION_ITERATOR_HPP
|
||||||
|
#define BOOST_PERMUTATION_ITERATOR_HPP
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
template< class ElementIterator
|
||||||
|
, class IndexIterator
|
||||||
|
, class ValueT = use_default
|
||||||
|
, class CategoryT = use_default
|
||||||
|
, class ReferenceT = use_default
|
||||||
|
, class DifferenceT = use_default >
|
||||||
|
class permutation_iterator
|
||||||
|
: public iterator_adaptor<
|
||||||
|
permutation_iterator<ElementIterator, IndexIterator, ValueT, CategoryT, ReferenceT, DifferenceT>
|
||||||
|
, ElementIterator, ValueT, CategoryT, ReferenceT, DifferenceT >
|
||||||
|
{
|
||||||
|
typedef iterator_adaptor<
|
||||||
|
permutation_iterator<ElementIterator, IndexIterator, ValueT, CategoryT, ReferenceT, DifferenceT>
|
||||||
|
, ElementIterator, ValueT, CategoryT, ReferenceT, DifferenceT > super_t;
|
||||||
|
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
public:
|
||||||
|
permutation_iterator() : order_it_() {}
|
||||||
|
|
||||||
|
explicit permutation_iterator(ElementIterator x, IndexIterator y)
|
||||||
|
: super_t(x), order_it_(y) {}
|
||||||
|
|
||||||
|
template<class OtherElementIterator, class OtherIndexIterator, class V, class C, class R, class D >
|
||||||
|
permutation_iterator(
|
||||||
|
permutation_iterator<OtherElementIterator, OtherIndexIterator, V, C, R, D> const& r
|
||||||
|
, typename enable_if_convertible<OtherElementIterator, ElementIterator>::type* = 0
|
||||||
|
, typename enable_if_convertible<OtherIndexIterator, IndexIterator>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(r.base())
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename super_t::reference dereference() const
|
||||||
|
{ return *(this->base() + *this->order_it_); }
|
||||||
|
|
||||||
|
void increment() { ++this->order_it_; }
|
||||||
|
void decrement() { --this->order_it_; }
|
||||||
|
|
||||||
|
void advance(typename super_t::difference_type n)
|
||||||
|
{
|
||||||
|
std::advance( order_it_, n );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class OtherElementIterator, class OtherIndexIterator, class V, class C, class R, class D >
|
||||||
|
typename super_t::difference_type
|
||||||
|
distance_to( permutation_iterator<OtherElementIterator, OtherIndexIterator, V, C, R, D> const& y ) const
|
||||||
|
{
|
||||||
|
return std::distance( this->order_it_, y.order_it_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class OtherElementIterator, class OtherIndexIterator, class V, class C, class R, class D >
|
||||||
|
bool
|
||||||
|
equal( permutation_iterator<OtherElementIterator, OtherIndexIterator, V, C, R, D> const& y ) const
|
||||||
|
{
|
||||||
|
return( y.order_it_ == this->order_it_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexIterator order_it_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class ElementIterator, class IndexIterator>
|
||||||
|
permutation_iterator<ElementIterator, IndexIterator>
|
||||||
|
make_permutation_iterator( ElementIterator e, IndexIterator i )
|
||||||
|
{
|
||||||
|
return permutation_iterator<ElementIterator, IndexIterator>( e, i );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif
|
71
include/boost/iterator/reverse_iterator.hpp
Normal file
71
include/boost/iterator/reverse_iterator.hpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_REVERSE_ITERATOR_23022003THW_HPP
|
||||||
|
#define BOOST_REVERSE_ITERATOR_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
template <class Iterator>
|
||||||
|
class reverse_iterator
|
||||||
|
: public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
|
||||||
|
{
|
||||||
|
typedef iterator_adaptor< reverse_iterator<Iterator>, Iterator > super_t;
|
||||||
|
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
public:
|
||||||
|
reverse_iterator() {}
|
||||||
|
|
||||||
|
explicit reverse_iterator(Iterator x)
|
||||||
|
: super_t(x) {}
|
||||||
|
|
||||||
|
template<class OtherIterator>
|
||||||
|
reverse_iterator(
|
||||||
|
reverse_iterator<OtherIterator> const& r
|
||||||
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(r.base())
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename super_t::reference dereference() const { return *boost::prior(this->base()); }
|
||||||
|
|
||||||
|
void increment() { --this->base_reference(); }
|
||||||
|
void decrement() { ++this->base_reference(); }
|
||||||
|
|
||||||
|
void advance(typename super_t::difference_type n)
|
||||||
|
{
|
||||||
|
this->base_reference() += -n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class OtherIterator>
|
||||||
|
typename super_t::difference_type
|
||||||
|
distance_to(reverse_iterator<OtherIterator> const& y) const
|
||||||
|
{
|
||||||
|
return this->base_reference() - y.base();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class BidirectionalIterator>
|
||||||
|
reverse_iterator<BidirectionalIterator> make_reverse_iterator(BidirectionalIterator x)
|
||||||
|
{
|
||||||
|
return reverse_iterator<BidirectionalIterator>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // BOOST_REVERSE_ITERATOR_23022003THW_HPP
|
170
include/boost/iterator/transform_iterator.hpp
Normal file
170
include/boost/iterator/transform_iterator.hpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
// (C) Copyright David Abrahams 2002.
|
||||||
|
// (C) Copyright Jeremy Siek 2002.
|
||||||
|
// (C) Copyright Thomas Witt 2002.
|
||||||
|
// Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
|
||||||
|
#define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
|
||||||
|
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/iterator/detail/enable_if.hpp>
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/type_traits/function_traits.hpp>
|
||||||
|
#include <boost/type_traits/is_const.hpp>
|
||||||
|
#include <boost/type_traits/is_class.hpp>
|
||||||
|
#include <boost/type_traits/is_function.hpp>
|
||||||
|
#include <boost/type_traits/is_reference.hpp>
|
||||||
|
#include <boost/type_traits/remove_const.hpp>
|
||||||
|
#include <boost/type_traits/remove_reference.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
|
||||||
|
class transform_iterator;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <class UnaryFunction>
|
||||||
|
struct function_object_result
|
||||||
|
{
|
||||||
|
typedef typename UnaryFunction::result_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
template <class Return, class Argument>
|
||||||
|
struct function_object_result<Return(*)(Argument)>
|
||||||
|
{
|
||||||
|
typedef Return type;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Compute the iterator_adaptor instantiation to be used for transform_iterator
|
||||||
|
template <class UnaryFunction, class Iterator, class Reference, class Value>
|
||||||
|
struct transform_iterator_base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// By default, dereferencing the iterator yields the same as
|
||||||
|
// the function. Do we need to adjust the way
|
||||||
|
// function_object_result is computed for the standard
|
||||||
|
// proposal (e.g. using Doug's result_of)?
|
||||||
|
typedef typename ia_dflt_help<
|
||||||
|
Reference
|
||||||
|
, function_object_result<UnaryFunction>
|
||||||
|
>::type reference;
|
||||||
|
|
||||||
|
// To get the default for Value: remove any reference on the
|
||||||
|
// result type, but retain any constness to signal
|
||||||
|
// non-writability. Note that if we adopt Thomas' suggestion
|
||||||
|
// to key non-writability *only* on the Reference argument,
|
||||||
|
// we'd need to strip constness here as well.
|
||||||
|
typedef typename ia_dflt_help<
|
||||||
|
Value
|
||||||
|
, remove_reference<reference>
|
||||||
|
>::type cv_value_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef iterator_adaptor<
|
||||||
|
transform_iterator<UnaryFunction, Iterator, Reference, Value>
|
||||||
|
, Iterator
|
||||||
|
, cv_value_type
|
||||||
|
, use_default // Leave the traversal category alone
|
||||||
|
, reference
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class UnaryFunction, class Iterator, class Reference, class Value>
|
||||||
|
class transform_iterator
|
||||||
|
: public detail::transform_iterator_base<UnaryFunction, Iterator, Reference, Value>::type
|
||||||
|
{
|
||||||
|
typedef typename
|
||||||
|
detail::transform_iterator_base<UnaryFunction, Iterator, Reference, Value>::type
|
||||||
|
super_t;
|
||||||
|
|
||||||
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
public:
|
||||||
|
transform_iterator() { }
|
||||||
|
|
||||||
|
transform_iterator(Iterator const& x, UnaryFunction f)
|
||||||
|
: super_t(x), m_f(f) { }
|
||||||
|
|
||||||
|
explicit transform_iterator(Iterator const& x)
|
||||||
|
: super_t(x)
|
||||||
|
{
|
||||||
|
// Pro8 is a little too aggressive about instantiating the
|
||||||
|
// body of this function.
|
||||||
|
#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||||
|
// don't provide this constructor if UnaryFunction is a
|
||||||
|
// function pointer type, since it will be 0. Too dangerous.
|
||||||
|
BOOST_STATIC_ASSERT(is_class<UnaryFunction>::value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class OtherIterator>
|
||||||
|
transform_iterator(
|
||||||
|
transform_iterator<UnaryFunction, OtherIterator, Reference, Value> const& t
|
||||||
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(t.base()), m_f(t.functor()) {}
|
||||||
|
|
||||||
|
UnaryFunction functor() const
|
||||||
|
{ return m_f; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename super_t::reference dereference() const
|
||||||
|
{ return m_f(*this->base()); }
|
||||||
|
|
||||||
|
// Probably should be the initial base class so it can be
|
||||||
|
// optimized away via EBO if it is an empty class.
|
||||||
|
UnaryFunction m_f;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class UnaryFunction, class Iterator>
|
||||||
|
transform_iterator<UnaryFunction, Iterator>
|
||||||
|
make_transform_iterator(Iterator it, UnaryFunction fun)
|
||||||
|
{
|
||||||
|
return transform_iterator<UnaryFunction, Iterator>(it, fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version which allows explicit specification of the UnaryFunction
|
||||||
|
// type.
|
||||||
|
//
|
||||||
|
// This generator is not provided if UnaryFunction is a function
|
||||||
|
// pointer type, because it's too dangerous: the default-constructed
|
||||||
|
// function pointer in the iterator be 0, leading to a runtime
|
||||||
|
// crash.
|
||||||
|
template <class UnaryFunction, class Iterator>
|
||||||
|
typename iterators::enable_if<
|
||||||
|
is_class<UnaryFunction> // We should probably find a cheaper test than is_class<>
|
||||||
|
, transform_iterator<UnaryFunction, Iterator>
|
||||||
|
>::type
|
||||||
|
make_transform_iterator(Iterator it)
|
||||||
|
{
|
||||||
|
return transform_iterator<UnaryFunction, Iterator>(it, UnaryFunction());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||||
|
template <class Return, class Argument, class Iterator>
|
||||||
|
transform_iterator< Return (*)(Argument), Iterator, Return>
|
||||||
|
make_transform_iterator(Iterator it, Return (*fun)(Argument))
|
||||||
|
{
|
||||||
|
return transform_iterator<Return (*)(Argument), Iterator, Return>(it, fun);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_undef.hpp>
|
||||||
|
|
||||||
|
#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
|
611
include/boost/iterator/zip_iterator.hpp
Executable file
611
include/boost/iterator/zip_iterator.hpp
Executable file
@ -0,0 +1,611 @@
|
|||||||
|
// (C) Copyright David Abrahams and Thomas Becker 2000. Permission to
|
||||||
|
// copy, use, modify, sell and distribute this software is granted
|
||||||
|
// provided this copyright notice appears in all copies. This software
|
||||||
|
// is provided "as is" without express or implied warranty, and with
|
||||||
|
// no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#ifndef 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>
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
# include <boost/type_traits/remove_cv.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/apply.hpp>
|
||||||
|
#include <boost/mpl/apply_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
|
||||||
|
{
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
typedef typename
|
||||||
|
iterator_traits<
|
||||||
|
typename boost::remove_cv<Iterator>::type
|
||||||
|
>::reference
|
||||||
|
type;
|
||||||
|
#else
|
||||||
|
typedef typename
|
||||||
|
iterator_traits<Iterator>::reference
|
||||||
|
type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Iterator>
|
||||||
|
typename apply<Iterator>::type operator()(Iterator& 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::apply_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::apply_if<
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
mpl::or_<
|
||||||
|
#endif
|
||||||
|
boost::is_same<Tuple, tuples::null_type>
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
, 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.
|
||||||
|
//
|
||||||
|
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_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, == 1200) // 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_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
|
@ -1,767 +0,0 @@
|
|||||||
// (C) Copyright David Abrahams 2000. Permission to copy, use,
|
|
||||||
// modify, sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
//
|
|
||||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
|
||||||
// sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
|
|
||||||
#ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_
|
|
||||||
#define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_
|
|
||||||
|
|
||||||
#include <boost/iterator.hpp>
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <boost/compressed_pair.hpp>
|
|
||||||
#include <boost/concept_check.hpp>
|
|
||||||
|
|
||||||
// I was having some problems with VC6. I couldn't tell whether our hack for
|
|
||||||
// stock GCC was causing problems so I needed an easy way to turn it on and
|
|
||||||
// off. Now we can test the hack with various compilers and still have an
|
|
||||||
// "out" if it doesn't work. -dwa 7/31/00
|
|
||||||
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES)
|
|
||||||
# define BOOST_RELOPS_AMBIGUITY_BUG 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// Just a "type envelope"; works around some MSVC deficiencies.
|
|
||||||
template <class T>
|
|
||||||
struct type {};
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// Concept checking classes that express the requirements for iterator
|
|
||||||
// policies and adapted types. These classes are mostly for
|
|
||||||
// documentation purposes, and are not used in this header file. They
|
|
||||||
// merely provide a more succinct statement of what is expected of the
|
|
||||||
// iterator policies.
|
|
||||||
|
|
||||||
template <class Policies, class Adapted, class Traits>
|
|
||||||
struct TrivialIteratorPoliciesConcept
|
|
||||||
{
|
|
||||||
typedef typename Traits::reference Reference;
|
|
||||||
void constraints() {
|
|
||||||
function_requires< AssignableConcept<Policies> >();
|
|
||||||
function_requires< DefaultConstructibleConcept<Policies> >();
|
|
||||||
function_requires< AssignableConcept<Adapted> >();
|
|
||||||
function_requires< DefaultConstructibleConcept<Adapted> >();
|
|
||||||
|
|
||||||
const_constraints();
|
|
||||||
}
|
|
||||||
void const_constraints() const {
|
|
||||||
Reference r = p.dereference(type<Reference>(), x);
|
|
||||||
b = p.equal(x, x);
|
|
||||||
}
|
|
||||||
Policies p;
|
|
||||||
Adapted x;
|
|
||||||
mutable bool b;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Policies, class Adapted, class Traits>
|
|
||||||
struct ForwardIteratorPoliciesConcept
|
|
||||||
{
|
|
||||||
void constraints() {
|
|
||||||
function_requires<
|
|
||||||
TrivialIteratorPoliciesConcept<Policies, Adapted, Traits>
|
|
||||||
>();
|
|
||||||
|
|
||||||
p.increment(x);
|
|
||||||
}
|
|
||||||
Policies p;
|
|
||||||
Adapted x;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Policies, class Adapted, class Traits>
|
|
||||||
struct BidirectionalIteratorPoliciesConcept
|
|
||||||
{
|
|
||||||
void constraints() {
|
|
||||||
function_requires<
|
|
||||||
ForwardIteratorPoliciesConcept<Policies, Adapted, Traits>
|
|
||||||
>();
|
|
||||||
|
|
||||||
p.decrement(x);
|
|
||||||
}
|
|
||||||
Policies p;
|
|
||||||
Adapted x;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Policies, class Adapted, class Traits>
|
|
||||||
struct RandomAccessIteratorPoliciesConcept
|
|
||||||
{
|
|
||||||
typedef typename Traits::difference_type DifferenceType;
|
|
||||||
void constraints() {
|
|
||||||
function_requires<
|
|
||||||
BidirectionalIteratorPoliciesConcept<Policies, Adapted, Traits>
|
|
||||||
>();
|
|
||||||
|
|
||||||
p.advance(x, n);
|
|
||||||
const_constraints();
|
|
||||||
}
|
|
||||||
void const_constraints() const {
|
|
||||||
n = p.distance(type<DifferenceType>(), x, x);
|
|
||||||
b = p.less(x, x);
|
|
||||||
}
|
|
||||||
Policies p;
|
|
||||||
Adapted x;
|
|
||||||
mutable DifferenceType n;
|
|
||||||
mutable bool b;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// Default policies for iterator adaptors. You can use this as a base
|
|
||||||
// class if you want to customize particular policies.
|
|
||||||
struct default_iterator_policies
|
|
||||||
{
|
|
||||||
// Some of these members were defined static, but Borland got confused
|
|
||||||
// and thought they were non-const. Also, Sun C++ does not like static
|
|
||||||
// function templates.
|
|
||||||
|
|
||||||
template <class Reference, class Iterator>
|
|
||||||
Reference dereference(type<Reference>, const Iterator& x) const
|
|
||||||
{ return *x; }
|
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
void increment(Iterator& x)
|
|
||||||
{ ++x; }
|
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
void decrement(Iterator& x)
|
|
||||||
{ --x; }
|
|
||||||
|
|
||||||
template <class Iterator, class DifferenceType>
|
|
||||||
void advance(Iterator& x, DifferenceType n)
|
|
||||||
{ x += n; }
|
|
||||||
|
|
||||||
template <class Difference, class Iterator1, class Iterator2>
|
|
||||||
Difference distance(type<Difference>, const Iterator1& x,
|
|
||||||
const Iterator2& y) const
|
|
||||||
{ return y - x; }
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2>
|
|
||||||
bool equal(const Iterator1& x, const Iterator2& y) const
|
|
||||||
{ return x == y; }
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2>
|
|
||||||
bool less(const Iterator1& x, const Iterator2& y) const
|
|
||||||
{ return x < y; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// putting the comparisons in a base class avoids the g++
|
|
||||||
// ambiguous overload bug due to the relops operators
|
|
||||||
|
|
||||||
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
|
|
||||||
template <class Derived, class Base>
|
|
||||||
struct iterator_comparisons : Base { };
|
|
||||||
|
|
||||||
template <class D1, class D2, class Base1, class Base2>
|
|
||||||
inline bool operator==(const iterator_comparisons<D1,Base1>& xb,
|
|
||||||
const iterator_comparisons<D2,Base2>& yb)
|
|
||||||
{
|
|
||||||
const D1& x = static_cast<const D1&>(xb);
|
|
||||||
const D2& y = static_cast<const D2&>(yb);
|
|
||||||
return x.policies().equal(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class D1, class D2, class Base1, class Base2>
|
|
||||||
inline bool operator!=(const iterator_comparisons<D1,Base1>& xb,
|
|
||||||
const iterator_comparisons<D2,Base2>& yb)
|
|
||||||
{
|
|
||||||
const D1& x = static_cast<const D1&>(xb);
|
|
||||||
const D2& y = static_cast<const D2&>(yb);
|
|
||||||
return !x.policies().equal(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class D1, class D2, class Base1, class Base2>
|
|
||||||
inline bool operator<(const iterator_comparisons<D1,Base1>& xb,
|
|
||||||
const iterator_comparisons<D2,Base2>& yb)
|
|
||||||
{
|
|
||||||
const D1& x = static_cast<const D1&>(xb);
|
|
||||||
const D2& y = static_cast<const D2&>(yb);
|
|
||||||
return x.policies().less(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class D1, class D2, class Base1, class Base2>
|
|
||||||
inline bool operator>(const iterator_comparisons<D1,Base1>& xb,
|
|
||||||
const iterator_comparisons<D2,Base2>& yb)
|
|
||||||
{
|
|
||||||
const D1& x = static_cast<const D1&>(xb);
|
|
||||||
const D2& y = static_cast<const D2&>(yb);
|
|
||||||
return x.policies().less(y.iter(), x.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class D1, class D2, class Base1, class Base2>
|
|
||||||
inline bool operator>=(const iterator_comparisons<D1,Base1>& xb,
|
|
||||||
const iterator_comparisons<D2,Base2>& yb)
|
|
||||||
{
|
|
||||||
const D1& x = static_cast<const D1&>(xb);
|
|
||||||
const D2& y = static_cast<const D2&>(yb);
|
|
||||||
return !x.policies().less(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class D1, class D2, class Base1, class Base2>
|
|
||||||
inline bool operator<=(const iterator_comparisons<D1,Base1>& xb,
|
|
||||||
const iterator_comparisons<D2,Base2>& yb)
|
|
||||||
{
|
|
||||||
const D1& x = static_cast<const D1&>(xb);
|
|
||||||
const D2& y = static_cast<const D2&>(yb);
|
|
||||||
return !x.policies().less(y.iter(), x.iter());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// Some compilers (SGI MIPSpro 7.1.3.3) instantiate/compile member functions
|
|
||||||
// whether or not they are used. The following functions make sure that
|
|
||||||
// when the base iterators do not support particular operators, those
|
|
||||||
// operators do not get used.
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// Dummy version for iterators that don't support member access
|
|
||||||
template <class Iter, class Cat>
|
|
||||||
inline typename Iter::pointer
|
|
||||||
operator_arrow(const Iter&, Cat) {
|
|
||||||
typedef typename Iter::pointer Pointer;
|
|
||||||
return Pointer();
|
|
||||||
}
|
|
||||||
// Real version
|
|
||||||
template <class Iter>
|
|
||||||
inline typename Iter::pointer
|
|
||||||
operator_arrow(const Iter& i, std::forward_iterator_tag) {
|
|
||||||
return &(*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dummy version for iterators that don't support member access
|
|
||||||
template <class Iter, class Diff, class Cat>
|
|
||||||
inline void advance_impl(const Iter&, Diff, Cat) { }
|
|
||||||
|
|
||||||
// Real version
|
|
||||||
template <class Iter, class Diff>
|
|
||||||
inline typename Iter::pointer
|
|
||||||
advance_impl(const Iter& i, Diff n, std::random_access_iterator_tag) {
|
|
||||||
#ifdef __MWERKS__
|
|
||||||
i.policies().advance<Iter>(iter(), n);
|
|
||||||
#else
|
|
||||||
i.policies().advance(iter(), n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// iterator_adaptor - A generalized adaptor around an existing
|
|
||||||
// iterator, which is itself an iterator
|
|
||||||
//
|
|
||||||
// Iterator - the iterator type being wrapped.
|
|
||||||
//
|
|
||||||
// Policies - a set of policies determining how the resulting iterator
|
|
||||||
// works.
|
|
||||||
//
|
|
||||||
// Traits - a class satisfying the same requirements as a specialization of
|
|
||||||
// std::iterator_traits for the resulting iterator.
|
|
||||||
//
|
|
||||||
template <class Iterator, class Policies,
|
|
||||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits
|
|
||||||
#else
|
|
||||||
class Traits = std::iterator_traits<Iterator>
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct iterator_adaptor :
|
|
||||||
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
|
|
||||||
iterator_comparisons<
|
|
||||||
iterator_adaptor<Iterator,Policies,Traits>,
|
|
||||||
#endif
|
|
||||||
boost::iterator<typename Traits::iterator_category,
|
|
||||||
typename Traits::value_type, typename Traits::difference_type,
|
|
||||||
typename Traits::pointer, typename Traits::reference>
|
|
||||||
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
|
|
||||||
>
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
typedef iterator_adaptor<Iterator, Policies, Traits> Self;
|
|
||||||
public:
|
|
||||||
typedef typename Traits::difference_type difference_type;
|
|
||||||
typedef typename Traits::value_type value_type;
|
|
||||||
typedef typename Traits::pointer pointer;
|
|
||||||
typedef typename Traits::reference reference;
|
|
||||||
typedef typename Traits::iterator_category iterator_category;
|
|
||||||
typedef Iterator iterator_type;
|
|
||||||
|
|
||||||
iterator_adaptor() { }
|
|
||||||
|
|
||||||
iterator_adaptor(const Iterator& iter, const Policies& p = Policies())
|
|
||||||
: m_iter_p(iter, p) {}
|
|
||||||
|
|
||||||
template <class OtherIter, class OtherTraits>
|
|
||||||
iterator_adaptor (const iterator_adaptor<OtherIter, Policies,
|
|
||||||
OtherTraits>& src)
|
|
||||||
: m_iter_p(src.iter(), src.policies()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
reference operator*() const {
|
|
||||||
return policies().dereference(type<reference>(), iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning(push)
|
|
||||||
# pragma warning( disable : 4284 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pointer operator->() const
|
|
||||||
{ return detail::operator_arrow(*this, iterator_category()); }
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
reference operator[](difference_type n) const
|
|
||||||
{ return *(*this + n); }
|
|
||||||
|
|
||||||
Self& operator++() {
|
|
||||||
#ifdef __MWERKS__
|
|
||||||
// Odd bug, MWERKS couldn't deduce the type for the member template
|
|
||||||
// Workaround by explicitly specifying the type.
|
|
||||||
policies().increment<Iterator>(iter());
|
|
||||||
#else
|
|
||||||
policies().increment(iter());
|
|
||||||
#endif
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Self operator++(int) { Self tmp(*this); ++*this; return tmp; }
|
|
||||||
|
|
||||||
Self& operator--() {
|
|
||||||
#ifdef __MWERKS__
|
|
||||||
policies().decrement<Iterator>(iter());
|
|
||||||
#else
|
|
||||||
policies().decrement(iter());
|
|
||||||
#endif
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Self operator--(int) { Self tmp(*this); --*this; return tmp; }
|
|
||||||
|
|
||||||
Self& operator+=(difference_type n) {
|
|
||||||
detail::advance_impl(*this, n, iterator_category());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Self& operator-=(difference_type n) {
|
|
||||||
detail::advance_impl(*this, -n, iterator_category());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator_type base() const { return m_iter_p.first(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef Policies policies_type;
|
|
||||||
compressed_pair<Iterator,Policies> m_iter_p;
|
|
||||||
public: // too many compilers have trouble when these are private.
|
|
||||||
Policies& policies() { return m_iter_p.second(); }
|
|
||||||
const Policies& policies() const { return m_iter_p.second(); }
|
|
||||||
Iterator& iter() { return m_iter_p.first(); }
|
|
||||||
const Iterator& iter() const { return m_iter_p.first(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <class Iterator, class Policies, class Traits>
|
|
||||||
iterator_adaptor<Iterator,Policies,Traits>
|
|
||||||
operator-(iterator_adaptor<Iterator,Policies,Traits> p, const typename Traits::difference_type x)
|
|
||||||
{
|
|
||||||
return p -= x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator, class Policies, class Traits>
|
|
||||||
iterator_adaptor<Iterator,Policies,Traits>
|
|
||||||
operator+(iterator_adaptor<Iterator,Policies,Traits> p, typename Traits::difference_type x)
|
|
||||||
{
|
|
||||||
return p += x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator, class Policies, class Traits>
|
|
||||||
iterator_adaptor<Iterator,Policies,Traits>
|
|
||||||
operator+(typename Traits::difference_type x, iterator_adaptor<Iterator,Policies,Traits> p)
|
|
||||||
{
|
|
||||||
return p += x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
typename Traits1::difference_type operator-(
|
|
||||||
const iterator_adaptor<Iterator1,Policies,Traits1>& x,
|
|
||||||
const iterator_adaptor<Iterator2,Policies,Traits2>& y )
|
|
||||||
{
|
|
||||||
typedef typename Traits1::difference_type difference_type;
|
|
||||||
return x.policies().distance(type<difference_type>(), y.iter(), x.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOST_RELOPS_AMBIGUITY_BUG
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
inline bool
|
|
||||||
operator==(const iterator_adaptor<Iterator1,Policies,Traits1>& x, const iterator_adaptor<Iterator2,Policies,Traits2>& y) {
|
|
||||||
return x.policies().equal(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
inline bool
|
|
||||||
operator<(const iterator_adaptor<Iterator1,Policies,Traits1>& x, const iterator_adaptor<Iterator2,Policies,Traits2>& y) {
|
|
||||||
return x.policies().less(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
inline bool
|
|
||||||
operator>(const iterator_adaptor<Iterator1,Policies,Traits1>& x,
|
|
||||||
const iterator_adaptor<Iterator2,Policies,Traits2>& y) {
|
|
||||||
return x.policies().less(y.iter(), x.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
inline bool
|
|
||||||
operator>=(const iterator_adaptor<Iterator1,Policies,Traits1>& x, const iterator_adaptor<Iterator2,Policies,Traits2>& y) {
|
|
||||||
return !x.policies().less(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
inline bool
|
|
||||||
operator<=(const iterator_adaptor<Iterator1,Policies,Traits1>& x,
|
|
||||||
const iterator_adaptor<Iterator2,Policies,Traits2>& y) {
|
|
||||||
return !x.policies().less(y.iter(), x.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2, class Policies, class Traits1, class Traits2>
|
|
||||||
inline bool
|
|
||||||
operator!=(const iterator_adaptor<Iterator1,Policies,Traits1>& x,
|
|
||||||
const iterator_adaptor<Iterator2,Policies,Traits2>& y) {
|
|
||||||
return !x.policies().equal(x.iter(), y.iter());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// iterator_adaptors - A type generator that simplifies creating
|
|
||||||
// mutable/const pairs of iterator adaptors.
|
|
||||||
|
|
||||||
template <class Iterator, class ConstIterator,
|
|
||||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits,
|
|
||||||
class ConstTraits,
|
|
||||||
#else
|
|
||||||
class Traits = std::iterator_traits<Iterator>,
|
|
||||||
class ConstTraits = std::iterator_traits<ConstIterator>,
|
|
||||||
#endif
|
|
||||||
class Policies = default_iterator_policies>
|
|
||||||
class iterator_adaptors
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef iterator_adaptor<Iterator, Policies, Traits> iterator;
|
|
||||||
typedef iterator_adaptor<ConstIterator, Policies, ConstTraits>
|
|
||||||
const_iterator;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Transform Iterator Adaptor
|
|
||||||
//
|
|
||||||
// Upon deference, apply some unary function object and return the
|
|
||||||
// result by value.
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction>
|
|
||||||
struct transform_iterator_policies : public default_iterator_policies
|
|
||||||
{
|
|
||||||
transform_iterator_policies() { }
|
|
||||||
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
|
|
||||||
|
|
||||||
template <class Reference, class Iterator>
|
|
||||||
Reference dereference(type<Reference>, const Iterator& iter) const
|
|
||||||
{ return m_f(*iter); }
|
|
||||||
|
|
||||||
AdaptableUnaryFunction m_f;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction, class IteratorTraits>
|
|
||||||
struct transform_iterator_traits {
|
|
||||||
typedef typename AdaptableUnaryFunction::result_type value_type;
|
|
||||||
typedef value_type reference;
|
|
||||||
typedef value_type* pointer;
|
|
||||||
typedef typename IteratorTraits::difference_type difference_type;
|
|
||||||
typedef typename IteratorTraits::iterator_category iterator_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction,
|
|
||||||
class Iterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits = std::iterator_traits<Iterator>
|
|
||||||
#else
|
|
||||||
class Traits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct transform_iterator
|
|
||||||
{
|
|
||||||
typedef transform_iterator_traits<AdaptableUnaryFunction,Traits>
|
|
||||||
TransTraits;
|
|
||||||
typedef iterator_adaptor<Iterator,
|
|
||||||
transform_iterator_policies<AdaptableUnaryFunction>, TransTraits>
|
|
||||||
type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Indirect Iterators Adaptor
|
|
||||||
|
|
||||||
// Given a pointer to pointers (or iterator to iterators),
|
|
||||||
// apply a double dereference inside operator*().
|
|
||||||
//
|
|
||||||
// We use the term "outer" to refer to the first level iterator type
|
|
||||||
// and "inner" to refer to the second level iterator type. For
|
|
||||||
// example, given T**, T* is the inner iterator type and T** is the
|
|
||||||
// outer iterator type. Also, const T* would be the const inner
|
|
||||||
// iterator.
|
|
||||||
|
|
||||||
// We tried to implement this with transform_iterator, but that required
|
|
||||||
// using boost::remove_ref, which is not compiler portable.
|
|
||||||
|
|
||||||
struct indirect_iterator_policies : public default_iterator_policies
|
|
||||||
{
|
|
||||||
template <class Reference, class Iterator>
|
|
||||||
Reference dereference(type<Reference>, const Iterator& x) const
|
|
||||||
{ return **x; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class OuterIterator, class InnerIterator,
|
|
||||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class OuterTraits,
|
|
||||||
class InnerTraits
|
|
||||||
#else
|
|
||||||
class OuterTraits = std::iterator_traits<OuterIterator>,
|
|
||||||
class InnerTraits = std::iterator_traits<InnerIterator>
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct indirect_traits
|
|
||||||
{
|
|
||||||
typedef typename OuterTraits::difference_type difference_type;
|
|
||||||
typedef typename InnerTraits::value_type value_type;
|
|
||||||
typedef typename InnerTraits::pointer pointer;
|
|
||||||
typedef typename InnerTraits::reference reference;
|
|
||||||
typedef typename OuterTraits::iterator_category iterator_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class OuterIterator, // Mutable or Immutable, does not matter
|
|
||||||
class InnerIterator, // Mutable -> mutable indirect iterator
|
|
||||||
// Immutable -> immutable indirect iterator
|
|
||||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class OuterTraits,
|
|
||||||
class InnerTraits
|
|
||||||
#else
|
|
||||||
class OuterTraits = std::iterator_traits<OuterIterator>,
|
|
||||||
class InnerTraits = std::iterator_traits<InnerIterator>
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct indirect_iterator
|
|
||||||
{
|
|
||||||
typedef iterator_adaptor<OuterIterator,
|
|
||||||
indirect_iterator_policies,
|
|
||||||
indirect_traits<OuterIterator, InnerIterator,
|
|
||||||
OuterTraits, InnerTraits>
|
|
||||||
> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class OuterIterator, // Mutable or Immutable, does not matter
|
|
||||||
class InnerIterator, // Mutable
|
|
||||||
class ConstInnerIterator, // Immutable
|
|
||||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class OuterTraits,
|
|
||||||
class InnerTraits,
|
|
||||||
class ConstInnerTraits
|
|
||||||
#else
|
|
||||||
class OuterTraits = std::iterator_traits<OuterIterator>,
|
|
||||||
class InnerTraits = std::iterator_traits<InnerIterator>,
|
|
||||||
class ConstInnerTraits = std::iterator_traits<ConstInnerIterator>
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct indirect_iterators
|
|
||||||
{
|
|
||||||
typedef iterator_adaptors<OuterIterator, OuterIterator,
|
|
||||||
indirect_traits<OuterIterator, InnerIterator,
|
|
||||||
OuterTraits, InnerTraits>,
|
|
||||||
indirect_traits<OuterIterator, ConstInnerIterator,
|
|
||||||
OuterTraits, ConstInnerTraits>,
|
|
||||||
indirect_iterator_policies
|
|
||||||
> Adaptors;
|
|
||||||
typedef typename Adaptors::iterator iterator;
|
|
||||||
typedef typename Adaptors::const_iterator const_iterator;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Reverse Iterators Adaptor
|
|
||||||
|
|
||||||
struct reverse_iterator_policies
|
|
||||||
{
|
|
||||||
template <class Reference, class Iterator>
|
|
||||||
Reference dereference(type<Reference>, const Iterator& x) const
|
|
||||||
{ return *boost::prior(x); }
|
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
void increment(Iterator& x) const
|
|
||||||
{ --x; }
|
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
void decrement(Iterator& x) const
|
|
||||||
{ ++x; }
|
|
||||||
|
|
||||||
template <class Iterator, class DifferenceType>
|
|
||||||
void advance(Iterator& x, DifferenceType n) const
|
|
||||||
{ x -= n; }
|
|
||||||
|
|
||||||
template <class Difference, class Iterator1, class Iterator2>
|
|
||||||
Difference distance(type<Difference>, const Iterator1& x,
|
|
||||||
const Iterator2& y) const
|
|
||||||
{ return x - y; }
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2>
|
|
||||||
bool equal(const Iterator1& x, const Iterator2& y) const
|
|
||||||
{ return x == y; }
|
|
||||||
|
|
||||||
template <class Iterator1, class Iterator2>
|
|
||||||
bool less(const Iterator1& x, const Iterator2& y) const
|
|
||||||
{ return y < x; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Iterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits = std::iterator_traits<Iterator>
|
|
||||||
#else
|
|
||||||
class Traits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct reverse_iterator
|
|
||||||
{
|
|
||||||
typedef iterator_adaptor<Iterator, reverse_iterator_policies,
|
|
||||||
Traits> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ConstIterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class ConstTraits = std::iterator_traits<ConstIterator>
|
|
||||||
#else
|
|
||||||
class ConstTraits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct const_reverse_iterator
|
|
||||||
{
|
|
||||||
typedef iterator_adaptor<ConstIterator, reverse_iterator_policies,
|
|
||||||
ConstTraits> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Iterator, class ConstIterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits = std::iterator_traits<Iterator>,
|
|
||||||
class ConstTraits = std::iterator_traits<ConstIterator>
|
|
||||||
#else
|
|
||||||
class Traits,
|
|
||||||
class ConstTraits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct reverse_iterators
|
|
||||||
{
|
|
||||||
typedef iterator_adaptors<Iterator,ConstIterator,Traits,ConstTraits,
|
|
||||||
reverse_iterator_policies> Adaptor;
|
|
||||||
typedef typename Adaptor::iterator iterator;
|
|
||||||
typedef typename Adaptor::const_iterator const_iterator;
|
|
||||||
};
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Projection Iterators Adaptor
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction>
|
|
||||||
struct projection_iterator_policies : public default_iterator_policies
|
|
||||||
{
|
|
||||||
projection_iterator_policies() { }
|
|
||||||
projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
|
|
||||||
|
|
||||||
template <class Reference, class Iterator>
|
|
||||||
Reference dereference (type<Reference>, Iterator const& iter) const {
|
|
||||||
return m_f(*iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
AdaptableUnaryFunction m_f;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction, class Traits>
|
|
||||||
struct projection_iterator_traits {
|
|
||||||
typedef typename AdaptableUnaryFunction::result_type value_type;
|
|
||||||
typedef value_type& reference;
|
|
||||||
typedef value_type* pointer;
|
|
||||||
typedef typename Traits::difference_type difference_type;
|
|
||||||
typedef typename Traits::iterator_category iterator_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction, class Traits>
|
|
||||||
struct const_projection_iterator_traits {
|
|
||||||
typedef typename AdaptableUnaryFunction::result_type value_type;
|
|
||||||
typedef value_type const& reference;
|
|
||||||
typedef value_type const* pointer;
|
|
||||||
typedef typename Traits::difference_type difference_type;
|
|
||||||
typedef typename Traits::iterator_category iterator_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction, class Iterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits = std::iterator_traits<Iterator>
|
|
||||||
#else
|
|
||||||
class Traits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct projection_iterator {
|
|
||||||
typedef projection_iterator_traits<AdaptableUnaryFunction, Traits>
|
|
||||||
Projection_Traits;
|
|
||||||
typedef iterator_adaptor<Iterator,
|
|
||||||
projection_iterator_policies<AdaptableUnaryFunction>,
|
|
||||||
Projection_Traits> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction, class Iterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits = std::iterator_traits<Iterator>
|
|
||||||
#else
|
|
||||||
class Traits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct const_projection_iterator {
|
|
||||||
typedef const_projection_iterator_traits<AdaptableUnaryFunction,
|
|
||||||
Traits> Projection_Traits;
|
|
||||||
typedef iterator_adaptor<Iterator,
|
|
||||||
projection_iterator_policies<AdaptableUnaryFunction>,
|
|
||||||
Projection_Traits> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AdaptableUnaryFunction, class Iterator, class ConstIterator,
|
|
||||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
class Traits = std::iterator_traits<Iterator>,
|
|
||||||
class ConstTraits = std::iterator_traits<ConstIterator>
|
|
||||||
#else
|
|
||||||
class Traits,
|
|
||||||
class ConstTraits
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
struct projection_iterators {
|
|
||||||
typedef projection_iterator_traits<AdaptableUnaryFunction, Traits>
|
|
||||||
Projection_Traits;
|
|
||||||
typedef const_projection_iterator_traits<AdaptableUnaryFunction,
|
|
||||||
ConstTraits> Const_Projection_Traits;
|
|
||||||
typedef iterator_adaptors<Iterator, ConstIterator,
|
|
||||||
Projection_Traits, Const_Projection_Traits,
|
|
||||||
projection_iterator_policies<AdaptableUnaryFunction> > Adaptors;
|
|
||||||
typedef typename Adaptors::iterator iterator;
|
|
||||||
typedef typename Adaptors::const_iterator const_iterator;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
50
test/Jamfile
Normal file
50
test/Jamfile
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
# modify, sell and distribute this software is granted provided this
|
||||||
|
# copyright notice appears in all copies. This software is provided
|
||||||
|
# "as is" without express or implied warranty, and with no claim as
|
||||||
|
# to its suitability for any purpose.
|
||||||
|
|
||||||
|
subproject libs/iterator/test ;
|
||||||
|
|
||||||
|
import testing ;
|
||||||
|
|
||||||
|
test-suite iterator
|
||||||
|
:
|
||||||
|
# These first two tests will run last, and are expected to fail
|
||||||
|
# for many less-capable compilers.
|
||||||
|
|
||||||
|
[ compile-fail interoperable_fail.cpp ]
|
||||||
|
# test uses expected success, so that we catch unrelated
|
||||||
|
# compilation problems.
|
||||||
|
[ run is_convertible_fail.cpp ]
|
||||||
|
|
||||||
|
[ run zip_iterator_test.cpp ]
|
||||||
|
|
||||||
|
# These tests should work for just about everything.
|
||||||
|
[ compile is_lvalue_iterator.cpp ]
|
||||||
|
[ compile is_readable_iterator.cpp ]
|
||||||
|
|
||||||
|
[ run unit_tests.cpp ]
|
||||||
|
[ run concept_tests.cpp ]
|
||||||
|
[ run iterator_adaptor_cc.cpp ]
|
||||||
|
[ run iterator_adaptor_test.cpp ]
|
||||||
|
[ compile iterator_archetype_cc.cpp ]
|
||||||
|
[ run transform_iterator_test.cpp ]
|
||||||
|
[ run indirect_iterator_test.cpp ]
|
||||||
|
[ run filter_iterator_test.cpp ]
|
||||||
|
[ run reverse_iterator_test.cpp ]
|
||||||
|
[ run counting_iterator_test.cpp ]
|
||||||
|
[ run permutation_iterator_test.cpp : : : # <stlport-iostream>on
|
||||||
|
]
|
||||||
|
|
||||||
|
[ run ../../utility/iterator_adaptor_examples.cpp ]
|
||||||
|
[ run ../../utility/counting_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/filter_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/fun_out_iter_example.cpp ]
|
||||||
|
[ run ../../utility/indirect_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/projection_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/reverse_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/transform_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/iterator_traits_test.cpp ]
|
||||||
|
|
||||||
|
;
|
44
test/Jamfile.v2
Normal file
44
test/Jamfile.v2
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
# modify, sell and distribute this software is granted provided this
|
||||||
|
# copyright notice appears in all copies. This software is provided
|
||||||
|
# "as is" without express or implied warranty, and with no claim as
|
||||||
|
# to its suitability for any purpose.
|
||||||
|
|
||||||
|
import testing ;
|
||||||
|
|
||||||
|
test-suite iterator
|
||||||
|
:
|
||||||
|
# These first two tests will run last, and are expected to fail
|
||||||
|
# for many less-capable compilers.
|
||||||
|
|
||||||
|
[ compile-fail interoperable_fail.cpp ]
|
||||||
|
# test uses expected success, so that we catch unrelated
|
||||||
|
# compilation problems.
|
||||||
|
[ run is_convertible_fail.cpp ]
|
||||||
|
|
||||||
|
# These tests should work for just about everything.
|
||||||
|
[ run unit_tests.cpp ]
|
||||||
|
[ run concept_tests.cpp ]
|
||||||
|
[ run iterator_adaptor_cc.cpp ]
|
||||||
|
[ run iterator_adaptor_test.cpp ]
|
||||||
|
[ compile iterator_archetype_cc.cpp ]
|
||||||
|
[ run transform_iterator_test.cpp ]
|
||||||
|
[ run indirect_iterator_test.cpp ]
|
||||||
|
[ run filter_iterator_test.cpp ]
|
||||||
|
[ run reverse_iterator_test.cpp ]
|
||||||
|
[ run counting_iterator_test.cpp ]
|
||||||
|
[ run permutation_iterator_test.cpp : : : # <stlport-iostream>on
|
||||||
|
]
|
||||||
|
[ run zip_iterator_test.cpp ]
|
||||||
|
|
||||||
|
[ run ../../utility/iterator_adaptor_examples.cpp ]
|
||||||
|
[ run ../../utility/counting_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/filter_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/fun_out_iter_example.cpp ]
|
||||||
|
[ run ../../utility/indirect_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/projection_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/reverse_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/transform_iterator_example.cpp ]
|
||||||
|
[ run ../../utility/iterator_traits_test.cpp ]
|
||||||
|
|
||||||
|
;
|
83
test/concept_tests.cpp
Normal file
83
test/concept_tests.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_concepts.hpp>
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
#include <boost/operators.hpp>
|
||||||
|
|
||||||
|
struct new_random_access
|
||||||
|
: std::random_access_iterator_tag
|
||||||
|
, boost::random_access_traversal_tag
|
||||||
|
{};
|
||||||
|
|
||||||
|
struct new_iterator
|
||||||
|
: public boost::iterator< new_random_access, int >
|
||||||
|
{
|
||||||
|
int& operator*() const { return *m_x; }
|
||||||
|
new_iterator& operator++() { return *this; }
|
||||||
|
new_iterator operator++(int) { return *this; }
|
||||||
|
new_iterator& operator--() { return *this; }
|
||||||
|
new_iterator operator--(int) { return *this; }
|
||||||
|
new_iterator& operator+=(std::ptrdiff_t) { return *this; }
|
||||||
|
new_iterator operator+(std::ptrdiff_t) { return *this; }
|
||||||
|
new_iterator& operator-=(std::ptrdiff_t) { return *this; }
|
||||||
|
std::ptrdiff_t operator-(const new_iterator&) const { return 0; }
|
||||||
|
new_iterator operator-(std::ptrdiff_t) const { return *this; }
|
||||||
|
bool operator==(const new_iterator&) const { return false; }
|
||||||
|
bool operator!=(const new_iterator&) const { return false; }
|
||||||
|
bool operator<(const new_iterator&) const { return false; }
|
||||||
|
int* m_x;
|
||||||
|
};
|
||||||
|
new_iterator operator+(std::ptrdiff_t, new_iterator x) { return x; }
|
||||||
|
|
||||||
|
struct old_iterator
|
||||||
|
: public boost::iterator<std::random_access_iterator_tag, int>
|
||||||
|
{
|
||||||
|
int& operator*() const { return *m_x; }
|
||||||
|
old_iterator& operator++() { return *this; }
|
||||||
|
old_iterator operator++(int) { return *this; }
|
||||||
|
old_iterator& operator--() { return *this; }
|
||||||
|
old_iterator operator--(int) { return *this; }
|
||||||
|
old_iterator& operator+=(std::ptrdiff_t) { return *this; }
|
||||||
|
old_iterator operator+(std::ptrdiff_t) { return *this; }
|
||||||
|
old_iterator& operator-=(std::ptrdiff_t) { return *this; }
|
||||||
|
old_iterator operator-(std::ptrdiff_t) const { return *this; }
|
||||||
|
std::ptrdiff_t operator-(const old_iterator&) const { return 0; }
|
||||||
|
bool operator==(const old_iterator&) const { return false; }
|
||||||
|
bool operator!=(const old_iterator&) const { return false; }
|
||||||
|
bool operator<(const old_iterator&) const { return false; }
|
||||||
|
int* m_x;
|
||||||
|
};
|
||||||
|
old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
boost::iterator_traversal<new_iterator>::type tc;
|
||||||
|
boost::random_access_traversal_tag derived = tc;
|
||||||
|
(void)derived;
|
||||||
|
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::WritableLvalueIteratorConcept<int*> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::RandomAccessTraversalConcept<int*> >();
|
||||||
|
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::ReadableLvalueIteratorConcept<const int*> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::RandomAccessTraversalConcept<const int*> >();
|
||||||
|
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::WritableLvalueIteratorConcept<new_iterator> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::RandomAccessTraversalConcept<new_iterator> >();
|
||||||
|
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::WritableLvalueIteratorConcept<old_iterator> >();
|
||||||
|
boost::function_requires<
|
||||||
|
boost_concepts::RandomAccessTraversalConcept<old_iterator> >();
|
||||||
|
return 0;
|
||||||
|
}
|
295
test/counting_iterator_test.cpp
Normal file
295
test/counting_iterator_test.cpp
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
|
||||||
|
// distribute this software is granted provided this copyright notice appears in
|
||||||
|
// all copies. This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
//
|
||||||
|
// Revision History
|
||||||
|
// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with
|
||||||
|
// plain MSVC again. (David Abrahams)
|
||||||
|
// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in
|
||||||
|
// MSVC without STLport, so that the other tests may proceed
|
||||||
|
// (David Abrahams)
|
||||||
|
// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)
|
||||||
|
// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)
|
||||||
|
// 24 Jan 2001 Initial revision (David Abrahams)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#ifdef __BORLANDC__ // Borland mis-detects our custom iterators
|
||||||
|
# pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator
|
||||||
|
# pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator<char> += n).
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
# pragma warning(disable:4786) // identifier truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/detail/iterator.hpp>
|
||||||
|
#include <boost/iterator/counting_iterator.hpp>
|
||||||
|
#include <boost/iterator/new_iterator_tests.hpp>
|
||||||
|
|
||||||
|
#include <boost/next_prior.hpp>
|
||||||
|
#include <boost/mpl/if.hpp>
|
||||||
|
#include <boost/detail/iterator.hpp>
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
#include <boost/limits.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <climits>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifndef __BORLANDC__
|
||||||
|
# include <boost/tuple/tuple.hpp>
|
||||||
|
#endif
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <cassert>
|
||||||
|
#ifndef BOOST_NO_SLIST
|
||||||
|
# include <slist>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||||
|
template <class T>
|
||||||
|
struct signed_assert_nonnegative
|
||||||
|
{
|
||||||
|
static void test(T x) { assert(x >= 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct unsigned_assert_nonnegative
|
||||||
|
{
|
||||||
|
static void test(T x) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct assert_nonnegative
|
||||||
|
: boost::mpl::if_c<
|
||||||
|
std::numeric_limits<T>::is_signed
|
||||||
|
, signed_assert_nonnegative<T>
|
||||||
|
, unsigned_assert_nonnegative<T>
|
||||||
|
>::type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Special tests for RandomAccess CountingIterators.
|
||||||
|
template <class CountingIterator, class Value>
|
||||||
|
void category_test(
|
||||||
|
CountingIterator start,
|
||||||
|
CountingIterator finish,
|
||||||
|
Value,
|
||||||
|
std::random_access_iterator_tag)
|
||||||
|
{
|
||||||
|
typedef typename
|
||||||
|
boost::detail::iterator_traits<CountingIterator>::difference_type
|
||||||
|
difference_type;
|
||||||
|
difference_type distance = boost::detail::distance(start, finish);
|
||||||
|
|
||||||
|
// Pick a random position internal to the range
|
||||||
|
difference_type offset = (unsigned)rand() % distance;
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||||
|
assert(offset >= 0);
|
||||||
|
#else
|
||||||
|
assert_nonnegative<difference_type>::test(offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CountingIterator internal = start;
|
||||||
|
std::advance(internal, offset);
|
||||||
|
|
||||||
|
// Try some binary searches on the range to show that it's ordered
|
||||||
|
assert(std::binary_search(start, finish, *internal));
|
||||||
|
|
||||||
|
// #including tuple crashed borland, so I had to give up on tie().
|
||||||
|
std::pair<CountingIterator,CountingIterator> xy(
|
||||||
|
std::equal_range(start, finish, *internal));
|
||||||
|
CountingIterator x = xy.first, y = xy.second;
|
||||||
|
|
||||||
|
assert(boost::detail::distance(x, y) == 1);
|
||||||
|
|
||||||
|
// Show that values outside the range can't be found
|
||||||
|
assert(!std::binary_search(start, boost::prior(finish), *finish));
|
||||||
|
|
||||||
|
// Do the generic random_access_iterator_test
|
||||||
|
typedef typename CountingIterator::value_type value_type;
|
||||||
|
std::vector<value_type> v;
|
||||||
|
for (value_type z = *start; !(z == *finish); ++z)
|
||||||
|
v.push_back(z);
|
||||||
|
|
||||||
|
// Note that this test requires a that the first argument is
|
||||||
|
// dereferenceable /and/ a valid iterator prior to the first argument
|
||||||
|
boost::random_access_iterator_test(start, v.size(), v.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special tests for bidirectional CountingIterators
|
||||||
|
template <class CountingIterator, class Value>
|
||||||
|
void category_test(CountingIterator start, Value v1, std::bidirectional_iterator_tag)
|
||||||
|
{
|
||||||
|
Value v2 = v1;
|
||||||
|
++v2;
|
||||||
|
|
||||||
|
// Note that this test requires a that the first argument is
|
||||||
|
// dereferenceable /and/ a valid iterator prior to the first argument
|
||||||
|
boost::bidirectional_iterator_test(start, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CountingIterator, class Value>
|
||||||
|
void category_test(CountingIterator start, CountingIterator finish, Value v1, std::forward_iterator_tag)
|
||||||
|
{
|
||||||
|
Value v2 = v1;
|
||||||
|
++v2;
|
||||||
|
if (finish != start && finish != boost::next(start))
|
||||||
|
boost::forward_readable_iterator_test(start, finish, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CountingIterator, class Value>
|
||||||
|
void test_aux(CountingIterator start, CountingIterator finish, Value v1)
|
||||||
|
{
|
||||||
|
typedef typename CountingIterator::iterator_category category;
|
||||||
|
typedef typename CountingIterator::value_type value_type;
|
||||||
|
|
||||||
|
// If it's a RandomAccessIterator we can do a few delicate tests
|
||||||
|
category_test(start, finish, v1, category());
|
||||||
|
|
||||||
|
// Okay, brute force...
|
||||||
|
for (CountingIterator p = start
|
||||||
|
; p != finish && boost::next(p) != finish
|
||||||
|
; ++p)
|
||||||
|
{
|
||||||
|
assert(boost::next(*p) == *boost::next(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prove that a reference can be formed to these values
|
||||||
|
typedef typename CountingIterator::value_type value;
|
||||||
|
const value* q = &*start;
|
||||||
|
(void)q; // suppress unused variable warning
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Incrementable>
|
||||||
|
void test(Incrementable start, Incrementable finish)
|
||||||
|
{
|
||||||
|
test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish), start);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer>
|
||||||
|
void test_integer(Integer* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Integer start = 0;
|
||||||
|
Integer finish = 120;
|
||||||
|
test(start, finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer, class Category, class Difference>
|
||||||
|
void test_integer3(Integer* = 0, Category* = 0, Difference* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Integer start = 0;
|
||||||
|
Integer finish = 120;
|
||||||
|
typedef boost::counting_iterator<Integer,Category,Difference> iterator;
|
||||||
|
test_aux(iterator(start), iterator(finish), start);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
void test_container(Container* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Container c(1 + (unsigned)rand() % 1673);
|
||||||
|
|
||||||
|
const typename Container::iterator start = c.begin();
|
||||||
|
|
||||||
|
// back off by 1 to leave room for dereferenceable value at the end
|
||||||
|
typename Container::iterator finish = start;
|
||||||
|
std::advance(finish, c.size() - 1);
|
||||||
|
|
||||||
|
test(start, finish);
|
||||||
|
|
||||||
|
typedef typename Container::const_iterator const_iterator;
|
||||||
|
test(const_iterator(start), const_iterator(finish));
|
||||||
|
}
|
||||||
|
|
||||||
|
class my_int1 {
|
||||||
|
public:
|
||||||
|
my_int1() { }
|
||||||
|
my_int1(int x) : m_int(x) { }
|
||||||
|
my_int1& operator++() { ++m_int; return *this; }
|
||||||
|
bool operator==(const my_int1& x) const { return m_int == x.m_int; }
|
||||||
|
private:
|
||||||
|
int m_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
class my_int2 {
|
||||||
|
public:
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void pointer;
|
||||||
|
typedef void reference;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
my_int2() { }
|
||||||
|
my_int2(int x) : m_int(x) { }
|
||||||
|
my_int2& operator++() { ++m_int; return *this; }
|
||||||
|
my_int2& operator--() { --m_int; return *this; }
|
||||||
|
bool operator==(const my_int2& x) const { return m_int == x.m_int; }
|
||||||
|
private:
|
||||||
|
int m_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
class my_int3 {
|
||||||
|
public:
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void pointer;
|
||||||
|
typedef void reference;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
my_int3() { }
|
||||||
|
my_int3(int x) : m_int(x) { }
|
||||||
|
my_int3& operator++() { ++m_int; return *this; }
|
||||||
|
my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
|
||||||
|
std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; }
|
||||||
|
my_int3& operator--() { --m_int; return *this; }
|
||||||
|
bool operator==(const my_int3& x) const { return m_int == x.m_int; }
|
||||||
|
bool operator!=(const my_int3& x) const { return m_int != x.m_int; }
|
||||||
|
bool operator<(const my_int3& x) const { return m_int < x.m_int; }
|
||||||
|
private:
|
||||||
|
int m_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Test the built-in integer types.
|
||||||
|
test_integer<char>();
|
||||||
|
test_integer<unsigned char>();
|
||||||
|
test_integer<signed char>();
|
||||||
|
test_integer<wchar_t>();
|
||||||
|
test_integer<short>();
|
||||||
|
test_integer<unsigned short>();
|
||||||
|
test_integer<int>();
|
||||||
|
test_integer<unsigned int>();
|
||||||
|
test_integer<long>();
|
||||||
|
test_integer<unsigned long>();
|
||||||
|
#if defined(BOOST_HAS_LONG_LONG)
|
||||||
|
test_integer<long long>();
|
||||||
|
test_integer<unsigned long long>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Test user-defined type.
|
||||||
|
|
||||||
|
test_integer3<my_int1, std::forward_iterator_tag, int>();
|
||||||
|
test_integer<my_int2>();
|
||||||
|
test_integer<my_int3>();
|
||||||
|
|
||||||
|
// Some tests on container iterators, to prove we handle a few different categories
|
||||||
|
test_container<std::vector<int> >();
|
||||||
|
test_container<std::list<int> >();
|
||||||
|
# ifndef BOOST_NO_SLIST
|
||||||
|
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// Also prove that we can handle raw pointers.
|
||||||
|
int array[2000];
|
||||||
|
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
80
test/filter_iterator_test.cpp
Normal file
80
test/filter_iterator_test.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
#include <boost/iterator/filter_iterator.hpp>
|
||||||
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
|
#include <boost/iterator/new_iterator_tests.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using boost::dummyT;
|
||||||
|
|
||||||
|
struct one_or_four
|
||||||
|
{
|
||||||
|
bool operator()(dummyT x) const
|
||||||
|
{
|
||||||
|
return x.foo() == 1 || x.foo() == 4;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> struct undefined;
|
||||||
|
|
||||||
|
// Test filter iterator
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||||
|
dummyT(3), dummyT(4), dummyT(5) };
|
||||||
|
const int N = sizeof(array)/sizeof(dummyT);
|
||||||
|
|
||||||
|
typedef boost::filter_iterator<one_or_four, dummyT*> filter_iter;
|
||||||
|
|
||||||
|
boost::bidirectional_readable_iterator_test(
|
||||||
|
filter_iter(one_or_four(), array, array+N)
|
||||||
|
, dummyT(1), dummyT(4));
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
(!boost::is_convertible<
|
||||||
|
boost::iterator_traversal<filter_iter>::type
|
||||||
|
, boost::random_access_traversal_tag
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
//# endif
|
||||||
|
|
||||||
|
// On compilers not supporting partial specialization, we can do more type
|
||||||
|
// deduction with deque iterators than with pointers... unless the library
|
||||||
|
// is broken ;-(
|
||||||
|
std::deque<dummyT> array2;
|
||||||
|
std::copy(array+0, array+N, std::back_inserter(array2));
|
||||||
|
boost::bidirectional_readable_iterator_test(
|
||||||
|
boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()),
|
||||||
|
dummyT(1), dummyT(4));
|
||||||
|
|
||||||
|
boost::bidirectional_readable_iterator_test(
|
||||||
|
boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()),
|
||||||
|
dummyT(1), dummyT(4));
|
||||||
|
|
||||||
|
boost::bidirectional_readable_iterator_test(
|
||||||
|
boost::make_filter_iterator(
|
||||||
|
one_or_four()
|
||||||
|
, boost::make_reverse_iterator(array2.end())
|
||||||
|
, boost::make_reverse_iterator(array2.begin())
|
||||||
|
),
|
||||||
|
dummyT(4), dummyT(1));
|
||||||
|
|
||||||
|
boost::bidirectional_readable_iterator_test(
|
||||||
|
filter_iter(array+0, array+N),
|
||||||
|
dummyT(1), dummyT(4));
|
||||||
|
|
||||||
|
boost::bidirectional_readable_iterator_test(
|
||||||
|
filter_iter(one_or_four(), array, array + N),
|
||||||
|
dummyT(1), dummyT(4));
|
||||||
|
|
||||||
|
std::cout << "test successful " << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
209
test/indirect_iterator_test.cpp
Normal file
209
test/indirect_iterator_test.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
// Revision History
|
||||||
|
// 22 Nov 2002 Thomas Witt
|
||||||
|
// Added interoperability check.
|
||||||
|
// 08 Mar 2001 Jeremy Siek
|
||||||
|
// Moved test of indirect iterator into its own file. It to
|
||||||
|
// to be in iterator_adaptor_test.cpp.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <boost/iterator/indirect_iterator.hpp>
|
||||||
|
#include <boost/iterator/iterator_concepts.hpp>
|
||||||
|
#include <boost/iterator/new_iterator_tests.hpp>
|
||||||
|
|
||||||
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
|
#include <boost/concept_archetype.hpp>
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#if !defined(__SGI_STL_PORT) \
|
||||||
|
&& (defined(BOOST_MSVC_STD_ITERATOR) \
|
||||||
|
|| BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \
|
||||||
|
|| BOOST_WORKAROUND(__GNUC__, <= 2))
|
||||||
|
|
||||||
|
// std container random-access iterators don't support mutable/const
|
||||||
|
// interoperability (but may support const/mutable interop).
|
||||||
|
# define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||||
|
|
||||||
|
using boost::dummyT;
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr<dummyT>)
|
||||||
|
|
||||||
|
typedef std::vector<int> storage;
|
||||||
|
typedef std::vector<int*> pointer_ra_container;
|
||||||
|
typedef std::set<storage::iterator> iterator_set;
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
struct indirect_iterator_pair_generator
|
||||||
|
{
|
||||||
|
typedef boost::indirect_iterator<typename Container::iterator> iterator;
|
||||||
|
|
||||||
|
typedef boost::indirect_iterator<
|
||||||
|
typename Container::iterator
|
||||||
|
, typename iterator::value_type const
|
||||||
|
> const_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
void more_indirect_iterator_tests()
|
||||||
|
{
|
||||||
|
storage store(1000);
|
||||||
|
std::generate(store.begin(), store.end(), rand);
|
||||||
|
|
||||||
|
pointer_ra_container ptr_ra_container;
|
||||||
|
iterator_set iter_set;
|
||||||
|
|
||||||
|
for (storage::iterator p = store.begin(); p != store.end(); ++p)
|
||||||
|
{
|
||||||
|
ptr_ra_container.push_back(&*p);
|
||||||
|
iter_set.insert(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef indirect_iterator_pair_generator<pointer_ra_container> indirect_ra_container;
|
||||||
|
|
||||||
|
indirect_ra_container::iterator db(ptr_ra_container.begin());
|
||||||
|
indirect_ra_container::iterator de(ptr_ra_container.end());
|
||||||
|
assert(static_cast<std::size_t>(de - db) == store.size());
|
||||||
|
assert(db + store.size() == de);
|
||||||
|
indirect_ra_container::const_iterator dci = db;
|
||||||
|
|
||||||
|
assert(dci == db);
|
||||||
|
|
||||||
|
#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
|
assert(db == dci);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(dci != de);
|
||||||
|
assert(dci < de);
|
||||||
|
assert(dci <= de);
|
||||||
|
|
||||||
|
#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
|
assert(de >= dci);
|
||||||
|
assert(de > dci);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dci = de;
|
||||||
|
assert(dci == de);
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
|
||||||
|
|
||||||
|
*db = 999;
|
||||||
|
assert(store.front() == 999);
|
||||||
|
|
||||||
|
// Borland C++ is getting very confused about the typedefs here
|
||||||
|
typedef boost::indirect_iterator<iterator_set::iterator> indirect_set_iterator;
|
||||||
|
typedef boost::indirect_iterator<
|
||||||
|
iterator_set::iterator
|
||||||
|
, iterator_set::iterator::value_type const
|
||||||
|
> const_indirect_set_iterator;
|
||||||
|
|
||||||
|
indirect_set_iterator sb(iter_set.begin());
|
||||||
|
indirect_set_iterator se(iter_set.end());
|
||||||
|
const_indirect_set_iterator sci(iter_set.begin());
|
||||||
|
assert(sci == sb);
|
||||||
|
|
||||||
|
# ifndef NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY
|
||||||
|
assert(se != sci);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
assert(sci != se);
|
||||||
|
sci = se;
|
||||||
|
assert(sci == se);
|
||||||
|
|
||||||
|
*boost::prior(se) = 888;
|
||||||
|
assert(store.back() == 888);
|
||||||
|
assert(std::equal(sb, se, store.begin()));
|
||||||
|
|
||||||
|
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
||||||
|
assert(std::equal(db, de, store.begin()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||||
|
dummyT(3), dummyT(4), dummyT(5) };
|
||||||
|
const int N = sizeof(array)/sizeof(dummyT);
|
||||||
|
|
||||||
|
typedef std::vector<boost::shared_ptr<dummyT> > shared_t;
|
||||||
|
shared_t shared;
|
||||||
|
|
||||||
|
// Concept checks
|
||||||
|
{
|
||||||
|
typedef boost::indirect_iterator<shared_t::iterator> iter_t;
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::detail::has_element_type<
|
||||||
|
boost::shared_ptr<dummyT>
|
||||||
|
// std::iterator_traits<shared_t::iterator>::value_type
|
||||||
|
>::value
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef boost::indirect_iterator<
|
||||||
|
shared_t::iterator
|
||||||
|
, boost::iterator_value<shared_t::iterator>::type const
|
||||||
|
> c_iter_t;
|
||||||
|
|
||||||
|
# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
|
boost::function_requires< boost_concepts::InteroperableConcept<iter_t, c_iter_t> >();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test indirect_iterator_generator
|
||||||
|
{
|
||||||
|
for (int jj = 0; jj < N; ++jj)
|
||||||
|
shared.push_back(boost::shared_ptr<dummyT>(new dummyT(jj)));
|
||||||
|
|
||||||
|
dummyT* ptr[N];
|
||||||
|
for (int k = 0; k < N; ++k)
|
||||||
|
ptr[k] = array + k;
|
||||||
|
|
||||||
|
typedef boost::indirect_iterator<dummyT**> indirect_iterator;
|
||||||
|
|
||||||
|
typedef boost::indirect_iterator<dummyT**, dummyT const>
|
||||||
|
const_indirect_iterator;
|
||||||
|
|
||||||
|
indirect_iterator i(ptr);
|
||||||
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(
|
||||||
|
boost::indirect_iterator<shared_t::iterator>(shared.begin())
|
||||||
|
, N, array);
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
||||||
|
|
||||||
|
// check operator->
|
||||||
|
assert((*i).m_x == i->foo());
|
||||||
|
|
||||||
|
const_indirect_iterator j(ptr);
|
||||||
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
|
||||||
|
|
||||||
|
dummyT const*const* const_ptr = ptr;
|
||||||
|
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
||||||
|
|
||||||
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
|
|
||||||
|
more_indirect_iterator_tests();
|
||||||
|
}
|
||||||
|
std::cout << "test successful " << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
22
test/interoperable_fail.cpp
Normal file
22
test/interoperable_fail.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright Thomas Witt 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#include <boost/iterator/indirect_iterator.hpp>
|
||||||
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
#include <boost/cstdlib.hpp>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef boost::reverse_iterator<std::list<int*>::iterator> rev_iter;
|
||||||
|
typedef boost::indirect_iterator<std::list<int*>::iterator> ind_iter;
|
||||||
|
|
||||||
|
ind_iter() == rev_iter();
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::exit_success;
|
||||||
|
}
|
11
test/is_convertible_fail.cpp
Normal file
11
test/is_convertible_fail.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
|
#include <boost/cstdlib.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
typedef boost::reverse_iterator<int*> rev_iter1;
|
||||||
|
typedef boost::reverse_iterator<char*> rev_iter2;
|
||||||
|
|
||||||
|
return boost::is_convertible<rev_iter1, rev_iter2>::value
|
||||||
|
? boost::exit_failure : boost::exit_success;
|
||||||
|
}
|
145
test/is_lvalue_iterator.cpp
Executable file
145
test/is_lvalue_iterator.cpp
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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)
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <iterator>
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||||
|
#include <boost/iterator/is_lvalue_iterator.hpp>
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
|
||||||
|
// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
struct v
|
||||||
|
{
|
||||||
|
v();
|
||||||
|
~v();
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(v)
|
||||||
|
|
||||||
|
struct value_iterator : boost::iterator<std::input_iterator_tag,v>
|
||||||
|
{
|
||||||
|
v operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::noncopyable>
|
||||||
|
{
|
||||||
|
boost::noncopyable const& operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct proxy_iterator
|
||||||
|
: boost::iterator<std::output_iterator_tag,T>
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||||
|
typedef boost::iterator<std::input_iterator_tag,value_type> base;
|
||||||
|
typedef base::iterator_category iterator_category;
|
||||||
|
typedef base::difference_type difference_type;
|
||||||
|
typedef base::pointer pointer;
|
||||||
|
typedef base::reference reference;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct proxy
|
||||||
|
{
|
||||||
|
operator value_type&() const;
|
||||||
|
proxy& operator=(value_type) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
proxy operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct lvalue_iterator
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
typedef T& reference;
|
||||||
|
typedef T difference_type;
|
||||||
|
typedef std::input_iterator_tag iterator_category;
|
||||||
|
typedef T* pointer;
|
||||||
|
|
||||||
|
T& operator*() const;
|
||||||
|
lvalue_iterator& operator++();
|
||||||
|
lvalue_iterator operator++(int);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct constant_lvalue_iterator
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
typedef T const& reference;
|
||||||
|
typedef T difference_type;
|
||||||
|
typedef std::input_iterator_tag iterator_category;
|
||||||
|
typedef T const* pointer;
|
||||||
|
|
||||||
|
T const& operator*() const;
|
||||||
|
constant_lvalue_iterator& operator++();
|
||||||
|
constant_lvalue_iterator operator++(int);
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<v>::proxy)
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<int>::proxy)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<v*>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<v const*>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::const_iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::ostream_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<int> >::value);
|
||||||
|
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<value_iterator>::value);
|
||||||
|
#endif
|
||||||
|
// Make sure inaccessible copy constructor doesn't prevent
|
||||||
|
// reference binding
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<noncopyable_iterator>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<int> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<char*> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<float> >::value);
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<int> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<float> >::value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<v*>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<v const*>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<std::deque<v>::iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::deque<v>::const_iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::ostream_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<int> >::value);
|
||||||
|
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<value_iterator>::value);
|
||||||
|
#endif
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<noncopyable_iterator>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<v> >::value);
|
||||||
|
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<int> >::value);
|
||||||
|
#endif
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<char*> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<float> >::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<int> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<float> >::value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
93
test/is_readable_iterator.cpp
Executable file
93
test/is_readable_iterator.cpp
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||||
|
// subject to 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)
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <iterator>
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||||
|
#include <boost/iterator/is_readable_iterator.hpp>
|
||||||
|
#include <boost/iterator.hpp>
|
||||||
|
|
||||||
|
// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
struct v
|
||||||
|
{
|
||||||
|
v();
|
||||||
|
~v();
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(v)
|
||||||
|
|
||||||
|
struct value_iterator : boost::iterator<std::input_iterator_tag,v>
|
||||||
|
{
|
||||||
|
v operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::noncopyable>
|
||||||
|
{
|
||||||
|
boost::noncopyable const& operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct proxy_iterator : boost::iterator<std::output_iterator_tag,v>
|
||||||
|
{
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||||
|
typedef boost::iterator<std::input_iterator_tag,v> base;
|
||||||
|
typedef base::iterator_category iterator_category;
|
||||||
|
typedef base::value_type value_type;
|
||||||
|
typedef base::difference_type difference_type;
|
||||||
|
typedef base::pointer pointer;
|
||||||
|
typedef base::reference reference;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct proxy
|
||||||
|
{
|
||||||
|
operator v&();
|
||||||
|
proxy& operator=(v) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
proxy operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct proxy_iterator2 : boost::iterator<std::output_iterator_tag,v>
|
||||||
|
{
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||||
|
typedef boost::iterator<std::input_iterator_tag,v> base;
|
||||||
|
typedef base::iterator_category iterator_category;
|
||||||
|
typedef base::value_type value_type;
|
||||||
|
typedef base::difference_type difference_type;
|
||||||
|
typedef base::pointer pointer;
|
||||||
|
typedef base::reference reference;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct proxy
|
||||||
|
{
|
||||||
|
proxy& operator=(v) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
proxy operator*() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<v*>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<v const*>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<std::deque<v>::iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<std::deque<v>::const_iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<std::back_insert_iterator<std::deque<v> > >::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<std::ostream_iterator<v> >::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<proxy_iterator>::value);
|
||||||
|
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<proxy_iterator2>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<value_iterator>::value);
|
||||||
|
|
||||||
|
// Make sure inaccessible copy constructor doesn't prevent
|
||||||
|
// readability
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<noncopyable_iterator>::value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
29
test/iterator_adaptor_cc.cpp
Normal file
29
test/iterator_adaptor_cc.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
|
#include <boost/iterator/iterator_concepts.hpp>
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
#include <boost/cstdlib.hpp>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef boost::reverse_iterator<int*> rev_iter;
|
||||||
|
typedef boost::reverse_iterator<int const*> c_rev_iter;
|
||||||
|
|
||||||
|
boost::function_requires< boost_concepts::WritableLvalueIteratorConcept<rev_iter> >();
|
||||||
|
boost::function_requires< boost_concepts::RandomAccessTraversalConcept<rev_iter> >();
|
||||||
|
boost::function_requires< boost::RandomAccessIteratorConcept<rev_iter> >();
|
||||||
|
boost::function_requires< boost_concepts::InteroperableConcept<rev_iter, c_rev_iter> >();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef boost::reverse_iterator<std::list<int>::iterator> rev_iter;
|
||||||
|
typedef boost::reverse_iterator<std::list<int>::const_iterator> c_rev_iter;
|
||||||
|
|
||||||
|
boost::function_requires< boost_concepts::ReadableLvalueIteratorConcept<c_rev_iter> >();
|
||||||
|
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<c_rev_iter> >();
|
||||||
|
boost::function_requires< boost::BidirectionalIteratorConcept<c_rev_iter> >();
|
||||||
|
boost::function_requires< boost_concepts::InteroperableConcept<rev_iter, c_rev_iter> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::exit_success;
|
||||||
|
}
|
323
test/iterator_adaptor_test.cpp
Normal file
323
test/iterator_adaptor_test.cpp
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
// (C) Copyright Thomas Witt 2003. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
# include <boost/iterator/is_readable_iterator.hpp>
|
||||||
|
# include <boost/iterator/is_lvalue_iterator.hpp>
|
||||||
|
#endif
|
||||||
|
#include <boost/pending/iterator_tests.hpp>
|
||||||
|
|
||||||
|
# include <boost/type_traits/broken_compiler_spec.hpp>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
|
#include <set>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "static_assert_same.hpp"
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
using boost::dummyT;
|
||||||
|
|
||||||
|
struct mult_functor {
|
||||||
|
typedef int result_type;
|
||||||
|
typedef int argument_type;
|
||||||
|
// Functors used with transform_iterator must be
|
||||||
|
// DefaultConstructible, as the transform_iterator must be
|
||||||
|
// DefaultConstructible to satisfy the requirements for
|
||||||
|
// TrivialIterator.
|
||||||
|
mult_functor() { }
|
||||||
|
mult_functor(int aa) : a(aa) { }
|
||||||
|
int operator()(int b) const { return a * b; }
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Pair>
|
||||||
|
struct select1st_
|
||||||
|
: public std::unary_function<Pair, typename Pair::first_type>
|
||||||
|
{
|
||||||
|
const typename Pair::first_type& operator()(const Pair& x) const {
|
||||||
|
return x.first;
|
||||||
|
}
|
||||||
|
typename Pair::first_type& operator()(Pair& x) const {
|
||||||
|
return x.first;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct one_or_four {
|
||||||
|
bool operator()(dummyT x) const {
|
||||||
|
return x.foo() == 1 || x.foo() == 4;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::deque<int> storage;
|
||||||
|
typedef std::deque<int*> pointer_deque;
|
||||||
|
typedef std::set<storage::iterator> iterator_set;
|
||||||
|
|
||||||
|
template <class T> struct foo;
|
||||||
|
|
||||||
|
void blah(int) { }
|
||||||
|
|
||||||
|
struct my_gen
|
||||||
|
{
|
||||||
|
typedef int result_type;
|
||||||
|
my_gen() : n(0) { }
|
||||||
|
int operator()() { return ++n; }
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class V>
|
||||||
|
struct ptr_iterator
|
||||||
|
: boost::iterator_adaptor<
|
||||||
|
ptr_iterator<V>
|
||||||
|
, V*
|
||||||
|
, V
|
||||||
|
, boost::random_access_traversal_tag
|
||||||
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
, V&
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::iterator_adaptor<
|
||||||
|
ptr_iterator<V>
|
||||||
|
, V*
|
||||||
|
, V
|
||||||
|
, boost::random_access_traversal_tag
|
||||||
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||||
|
, V&
|
||||||
|
#endif
|
||||||
|
> super_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ptr_iterator() { }
|
||||||
|
ptr_iterator(V* d) : super_t(d) { }
|
||||||
|
|
||||||
|
template <class V2>
|
||||||
|
ptr_iterator(
|
||||||
|
const ptr_iterator<V2>& x
|
||||||
|
, typename boost::enable_if_convertible<V2*, V*>::type* = 0
|
||||||
|
)
|
||||||
|
: super_t(x.base())
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-functional iterator for category modification checking
|
||||||
|
template <class Iter, class Traversal>
|
||||||
|
struct modify_traversal
|
||||||
|
: boost::iterator_adaptor<
|
||||||
|
modify_traversal<Iter, Traversal>
|
||||||
|
, Iter
|
||||||
|
, boost::use_default
|
||||||
|
, Traversal
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct fwd_iterator
|
||||||
|
: boost::iterator_adaptor<
|
||||||
|
fwd_iterator<T>
|
||||||
|
, boost::forward_iterator_archetype<T>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::iterator_adaptor<
|
||||||
|
fwd_iterator<T>
|
||||||
|
, boost::forward_iterator_archetype<T>
|
||||||
|
> super_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fwd_iterator() { }
|
||||||
|
fwd_iterator(boost::forward_iterator_archetype<T> d) : super_t(d) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct in_iterator
|
||||||
|
: boost::iterator_adaptor<
|
||||||
|
in_iterator<T>
|
||||||
|
, boost::input_iterator_archetype<T>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::iterator_adaptor<
|
||||||
|
in_iterator<T>
|
||||||
|
, boost::input_iterator_archetype<T>
|
||||||
|
> super_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
in_iterator() { }
|
||||||
|
in_iterator(boost::input_iterator_archetype<T> d) : super_t(d) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct constant_iterator
|
||||||
|
: boost::iterator_adaptor<
|
||||||
|
constant_iterator<Iter>
|
||||||
|
, Iter
|
||||||
|
, typename std::iterator_traits<Iter>::value_type const
|
||||||
|
>
|
||||||
|
{
|
||||||
|
typedef boost::iterator_adaptor<
|
||||||
|
constant_iterator<Iter>
|
||||||
|
, Iter
|
||||||
|
, typename std::iterator_traits<Iter>::value_type const
|
||||||
|
> base_t;
|
||||||
|
|
||||||
|
constant_iterator() {}
|
||||||
|
constant_iterator(Iter it)
|
||||||
|
: base_t(it) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
char (& traversal2(boost::incrementable_traversal_tag) )[1];
|
||||||
|
char (& traversal2(boost::single_pass_traversal_tag ) )[2];
|
||||||
|
char (& traversal2(boost::forward_traversal_tag ) )[3];
|
||||||
|
char (& traversal2(boost::bidirectional_traversal_tag) )[4];
|
||||||
|
char (& traversal2(boost::random_access_traversal_tag) )[5];
|
||||||
|
|
||||||
|
template <class Cat>
|
||||||
|
struct traversal3
|
||||||
|
{
|
||||||
|
static typename boost::iterator_category_to_traversal<Cat>::type x;
|
||||||
|
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x)));
|
||||||
|
typedef char (&type)[value];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Cat>
|
||||||
|
typename traversal3<Cat>::type traversal(Cat);
|
||||||
|
|
||||||
|
template <class Iter, class Trav>
|
||||||
|
int static_assert_traversal(Iter* = 0, Trav* = 0)
|
||||||
|
{
|
||||||
|
typedef typename boost::iterator_category_to_traversal<
|
||||||
|
BOOST_DEDUCED_TYPENAME Iter::iterator_category
|
||||||
|
>::type t2;
|
||||||
|
|
||||||
|
return static_assert_same<Trav,t2>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||||
|
dummyT(3), dummyT(4), dummyT(5) };
|
||||||
|
const int N = sizeof(array)/sizeof(dummyT);
|
||||||
|
|
||||||
|
// sanity check, if this doesn't pass the test is buggy
|
||||||
|
boost::random_access_iterator_test(array, N, array);
|
||||||
|
|
||||||
|
// Test the iterator_adaptor
|
||||||
|
{
|
||||||
|
ptr_iterator<dummyT> i(array);
|
||||||
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
|
ptr_iterator<const dummyT> j(array);
|
||||||
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
|
}
|
||||||
|
|
||||||
|
int test;
|
||||||
|
// Test the iterator_traits
|
||||||
|
{
|
||||||
|
// Test computation of defaults
|
||||||
|
typedef ptr_iterator<int> Iter1;
|
||||||
|
// don't use std::iterator_traits here to avoid VC++ problems
|
||||||
|
test = static_assert_same<Iter1::value_type, int>::value;
|
||||||
|
test = static_assert_same<Iter1::reference, int&>::value;
|
||||||
|
test = static_assert_same<Iter1::pointer, int*>::value;
|
||||||
|
test = static_assert_same<Iter1::difference_type, std::ptrdiff_t>::value;
|
||||||
|
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_convertible<Iter1::iterator_category, std::random_access_iterator_tag>::value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test computation of default when the Value is const
|
||||||
|
typedef ptr_iterator<int const> Iter1;
|
||||||
|
test = static_assert_same<Iter1::value_type, int>::value;
|
||||||
|
test = static_assert_same<Iter1::reference, const int&>::value;
|
||||||
|
|
||||||
|
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_readable_iterator<Iter1>::value);
|
||||||
|
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter1>::value);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
|
||||||
|
test = static_assert_same<Iter1::pointer, int const*>::value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test constant iterator idiom
|
||||||
|
typedef ptr_iterator<int> BaseIter;
|
||||||
|
typedef constant_iterator<BaseIter> Iter;
|
||||||
|
|
||||||
|
test = static_assert_same<Iter::value_type, int>::value;
|
||||||
|
test = static_assert_same<Iter::reference, int const&>::value;
|
||||||
|
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
|
||||||
|
test = static_assert_same<Iter::pointer, int const*>::value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
|
||||||
|
|
||||||
|
static_assert_traversal<BaseIter,boost::random_access_traversal_tag>();
|
||||||
|
static_assert_traversal<IncrementableIter,boost::incrementable_traversal_tag>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the iterator_adaptor
|
||||||
|
{
|
||||||
|
ptr_iterator<dummyT> i(array);
|
||||||
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
|
ptr_iterator<const dummyT> j(array);
|
||||||
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check operator-> with a forward iterator
|
||||||
|
{
|
||||||
|
boost::forward_iterator_archetype<dummyT> forward_iter;
|
||||||
|
|
||||||
|
typedef fwd_iterator<dummyT> adaptor_type;
|
||||||
|
|
||||||
|
adaptor_type i(forward_iter);
|
||||||
|
int zero = 0;
|
||||||
|
if (zero) // don't do this, just make sure it compiles
|
||||||
|
assert((*i).m_x == i->foo());
|
||||||
|
}
|
||||||
|
|
||||||
|
// check operator-> with an input iterator
|
||||||
|
{
|
||||||
|
boost::input_iterator_archetype<dummyT> input_iter;
|
||||||
|
typedef in_iterator<dummyT> adaptor_type;
|
||||||
|
adaptor_type i(input_iter);
|
||||||
|
int zero = 0;
|
||||||
|
if (zero) // don't do this, just make sure it compiles
|
||||||
|
assert((*i).m_x == i->foo());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "test successful " << std::endl;
|
||||||
|
(void)test;
|
||||||
|
return 0;
|
||||||
|
}
|
26
test/iterator_archetype_cc.cpp
Normal file
26
test/iterator_archetype_cc.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Copyright Thomas Witt 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
#include <boost/iterator/iterator_archetypes.hpp>
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
#include <boost/iterator/iterator_concepts.hpp>
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
typedef boost::iterator_archetype<
|
||||||
|
int
|
||||||
|
, boost::iterator_archetypes::writable_lvalue_iterator_t
|
||||||
|
, boost::random_access_traversal_tag
|
||||||
|
> iter;
|
||||||
|
|
||||||
|
boost::function_requires< boost_concepts::WritableLvalueIteratorConcept<iter> >();
|
||||||
|
boost::function_requires< boost_concepts::RandomAccessTraversalConcept<iter> >();
|
||||||
|
|
||||||
|
return 0; // keep msvc happy
|
||||||
|
}
|
||||||
|
|
84
test/permutation_iterator_test.cpp
Normal file
84
test/permutation_iterator_test.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// (C) Copyright Toon Knapen 2001.
|
||||||
|
// (C) Copyright Roland Richter 2003.
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/test/minimal.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/permutation_iterator.hpp>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
void permutation_test()
|
||||||
|
{
|
||||||
|
// Example taken from documentation of old permutation_iterator.
|
||||||
|
typedef std::vector< int > element_range_type;
|
||||||
|
typedef std::list< int > index_type;
|
||||||
|
|
||||||
|
const int element_range_size = 10;
|
||||||
|
const int index_size = 7;
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(index_size <= element_range_size);
|
||||||
|
element_range_type elements( element_range_size );
|
||||||
|
for( element_range_type::iterator el_it = elements.begin(); el_it != elements.end(); ++el_it )
|
||||||
|
{ *el_it = std::distance(elements.begin(), el_it); }
|
||||||
|
|
||||||
|
index_type indices( index_size );
|
||||||
|
for( index_type::iterator i_it = indices.begin(); i_it != indices.end(); ++i_it )
|
||||||
|
{ *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); }
|
||||||
|
std::reverse( indices.begin(), indices.end() );
|
||||||
|
|
||||||
|
typedef boost::permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type;
|
||||||
|
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
|
||||||
|
permutation_type it = begin;
|
||||||
|
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
|
||||||
|
|
||||||
|
BOOST_CHECK( it == begin );
|
||||||
|
BOOST_CHECK( it != end );
|
||||||
|
|
||||||
|
BOOST_CHECK( std::distance( begin, end ) == index_size );
|
||||||
|
|
||||||
|
for( index_type::iterator i_it1 = indices.begin(); it != end; ++i_it1, ++it )
|
||||||
|
{
|
||||||
|
BOOST_CHECK( *it == elements[ *i_it1 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
it = begin;
|
||||||
|
for( int i1 = 0; i1 < index_size - 1 ; i1+=2, it+=2 )
|
||||||
|
{
|
||||||
|
index_type::iterator i_it2 = indices.begin();
|
||||||
|
std::advance( i_it2, i1 );
|
||||||
|
BOOST_CHECK( *it == elements[ *i_it2 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
it = begin + (index_size);
|
||||||
|
for( index_type::iterator i_it3 = indices.end(); it != begin; )
|
||||||
|
{
|
||||||
|
BOOST_CHECK( *--it == elements[ *--i_it3 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
it = begin + index_size;
|
||||||
|
for( int i2 = 0; i2 < index_size - 1; i2+=2, --it )
|
||||||
|
{
|
||||||
|
index_type::iterator i_it4 = --indices.end();
|
||||||
|
std::advance( i_it4, -i2 );
|
||||||
|
BOOST_CHECK( *--it == elements[ *i_it4 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int test_main(int, char *[])
|
||||||
|
{
|
||||||
|
permutation_test();
|
||||||
|
return 0;
|
||||||
|
}
|
85
test/reverse_iterator_test.cpp
Normal file
85
test/reverse_iterator_test.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright Thomas Witt 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
|
#include <boost/iterator/new_iterator_tests.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
using boost::dummyT;
|
||||||
|
|
||||||
|
// Test reverse iterator
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||||
|
dummyT(3), dummyT(4), dummyT(5) };
|
||||||
|
const int N = sizeof(array)/sizeof(dummyT);
|
||||||
|
|
||||||
|
// Test reverse_iterator_generator
|
||||||
|
{
|
||||||
|
dummyT reversed[N];
|
||||||
|
std::copy(array, array + N, reversed);
|
||||||
|
std::reverse(reversed, reversed + N);
|
||||||
|
|
||||||
|
typedef boost::reverse_iterator<dummyT*> reverse_iterator;
|
||||||
|
|
||||||
|
reverse_iterator i(reversed + N);
|
||||||
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
||||||
|
|
||||||
|
typedef boost::reverse_iterator<const dummyT*> const_reverse_iterator;
|
||||||
|
|
||||||
|
const_reverse_iterator j(reversed + N);
|
||||||
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
|
||||||
|
const dummyT* const_reversed = reversed;
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||||
|
|
||||||
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test reverse_iterator_generator again, with traits fully deducible on all platforms
|
||||||
|
{
|
||||||
|
std::deque<dummyT> reversed_container;
|
||||||
|
std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
|
||||||
|
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
|
||||||
|
|
||||||
|
|
||||||
|
typedef boost::reverse_iterator<
|
||||||
|
std::deque<dummyT>::iterator> reverse_iterator;
|
||||||
|
typedef boost::reverse_iterator<
|
||||||
|
std::deque<dummyT>::const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
|
// MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
|
||||||
|
// (e.g. "reversed + N") is used in the constructor below.
|
||||||
|
const std::deque<dummyT>::iterator finish = reversed_container.end();
|
||||||
|
reverse_iterator i(finish);
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
||||||
|
|
||||||
|
const_reverse_iterator j = reverse_iterator(finish);
|
||||||
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
|
||||||
|
const std::deque<dummyT>::const_iterator const_reversed = reversed;
|
||||||
|
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||||
|
|
||||||
|
// Many compilers' builtin deque iterators don't interoperate well, though
|
||||||
|
// STLport fixes that problem.
|
||||||
|
#if defined(__SGI_STL_PORT) \
|
||||||
|
|| !BOOST_WORKAROUND(__GNUC__, <= 2) \
|
||||||
|
&& !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) \
|
||||||
|
&& !BOOST_WORKAROUND(__LIBCOMO_VERSION__, BOOST_TESTED_AT(29)) \
|
||||||
|
&& !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 1)
|
||||||
|
|
||||||
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
35
test/static_assert_same.hpp
Normal file
35
test/static_assert_same.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#ifndef STATIC_ASSERT_SAME_DWA2003530_HPP
|
||||||
|
# define STATIC_ASSERT_SAME_DWA2003530_HPP
|
||||||
|
|
||||||
|
# include <boost/type.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
template <class T, class U>
|
||||||
|
struct static_assert_same_base;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct static_assert_same_base<T,T>
|
||||||
|
{
|
||||||
|
enum { value = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
struct static_assert_same : static_assert_same_base<T,U> {};
|
||||||
|
|
||||||
|
#else
|
||||||
|
# include <boost/mpl/if.hpp>
|
||||||
|
# include <boost/mpl/bool.hpp>
|
||||||
|
# include <boost/type_traits/is_same.hpp>
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
struct static_assert_same
|
||||||
|
: boost::mpl::if_<boost::is_same<T,U>,boost::mpl::true_,void>::type
|
||||||
|
{};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // STATIC_ASSERT_SAME_DWA2003530_HPP
|
246
test/transform_iterator_test.cpp
Normal file
246
test/transform_iterator_test.cpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
|
||||||
|
// sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
|
// Revision History
|
||||||
|
// 22 Nov 2002 Thomas Witt
|
||||||
|
// Added interoperability check.
|
||||||
|
// 28 Oct 2002 Jeremy Siek
|
||||||
|
// Updated for new iterator adaptors.
|
||||||
|
// 08 Mar 2001 Jeremy Siek
|
||||||
|
// Moved test of transform iterator into its own file. It to
|
||||||
|
// to be in iterator_adaptor_test.cpp.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
|
#include <boost/iterator/iterator_concepts.hpp>
|
||||||
|
#include <boost/iterator/new_iterator_tests.hpp>
|
||||||
|
#include <boost/pending/iterator_tests.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/concept_check.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
namespace boost { namespace detail
|
||||||
|
{
|
||||||
|
template<> struct function_object_result<int (*)(int)>
|
||||||
|
{
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mult_functor {
|
||||||
|
// Functors used with transform_iterator must be
|
||||||
|
// DefaultConstructible, as the transform_iterator must be
|
||||||
|
// DefaultConstructible to satisfy the requirements for
|
||||||
|
// TrivialIterator.
|
||||||
|
mult_functor() { }
|
||||||
|
mult_functor(int aa) : a(aa) { }
|
||||||
|
int operator()(int b) const { return a * b; }
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct adaptable_mult_functor
|
||||||
|
: mult_functor
|
||||||
|
{
|
||||||
|
typedef int result_type;
|
||||||
|
typedef int argument_type;
|
||||||
|
// Functors used with transform_iterator must be
|
||||||
|
// DefaultConstructible, as the transform_iterator must be
|
||||||
|
// DefaultConstructible to satisfy the requirements for
|
||||||
|
// TrivialIterator.
|
||||||
|
adaptable_mult_functor() { }
|
||||||
|
adaptable_mult_functor(int aa) : mult_functor(aa) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct select_first
|
||||||
|
{
|
||||||
|
typedef int& result_type;
|
||||||
|
|
||||||
|
int& operator()(std::pair<int, int>& p) const
|
||||||
|
{
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct select_second
|
||||||
|
{
|
||||||
|
typedef int& result_type;
|
||||||
|
|
||||||
|
int& operator()(std::pair<int, int>& p) const
|
||||||
|
{
|
||||||
|
return p.second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct const_select_first
|
||||||
|
{
|
||||||
|
typedef int const& result_type;
|
||||||
|
|
||||||
|
int const& operator()(std::pair<int, int>const& p) const
|
||||||
|
{
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct value_select_first
|
||||||
|
{
|
||||||
|
typedef int result_type;
|
||||||
|
|
||||||
|
int operator()(std::pair<int, int>const& p) const
|
||||||
|
{
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int mult_2(int arg)
|
||||||
|
{
|
||||||
|
return arg*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
const int N = 10;
|
||||||
|
|
||||||
|
// Concept checks
|
||||||
|
{
|
||||||
|
typedef boost::transform_iterator<adaptable_mult_functor, int*> iter_t;
|
||||||
|
typedef boost::transform_iterator<adaptable_mult_functor, int const*> c_iter_t;
|
||||||
|
|
||||||
|
boost::function_requires< boost_concepts::InteroperableConcept<iter_t, c_iter_t> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test transform_iterator
|
||||||
|
{
|
||||||
|
int x[N], y[N];
|
||||||
|
for (int k = 0; k < N; ++k)
|
||||||
|
x[k] = k;
|
||||||
|
std::copy(x, x + N, y);
|
||||||
|
|
||||||
|
for (int k2 = 0; k2 < N; ++k2)
|
||||||
|
x[k2] = x[k2] * 2;
|
||||||
|
|
||||||
|
typedef boost::transform_iterator<adaptable_mult_functor, int*> iter_t;
|
||||||
|
iter_t i(y, adaptable_mult_functor(2));
|
||||||
|
boost::input_iterator_test(i, x[0], x[1]);
|
||||||
|
boost::input_iterator_test(iter_t(&y[0], adaptable_mult_functor(2)), x[0], x[1]);
|
||||||
|
|
||||||
|
boost::random_access_readable_iterator_test(i, N, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test transform_iterator non adaptable functor
|
||||||
|
{
|
||||||
|
int x[N], y[N];
|
||||||
|
for (int k = 0; k < N; ++k)
|
||||||
|
x[k] = k;
|
||||||
|
std::copy(x, x + N, y);
|
||||||
|
|
||||||
|
for (int k2 = 0; k2 < N; ++k2)
|
||||||
|
x[k2] = x[k2] * 2;
|
||||||
|
|
||||||
|
typedef boost::transform_iterator<mult_functor, int*, int> iter_t;
|
||||||
|
iter_t i(y, mult_functor(2));
|
||||||
|
boost::input_iterator_test(i, x[0], x[1]);
|
||||||
|
boost::input_iterator_test(iter_t(&y[0], mult_functor(2)), x[0], x[1]);
|
||||||
|
|
||||||
|
boost::random_access_readable_iterator_test(i, N, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test transform_iterator default argument handling
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef boost::transform_iterator<adaptable_mult_functor, int*, float> iter_t;
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, float>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, float>::value));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
typedef boost::transform_iterator<adaptable_mult_functor, int*, boost::use_default, float> iter_t;
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, int>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, float>::value));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
typedef boost::transform_iterator<adaptable_mult_functor, int*, float, double> iter_t;
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, float>::value));
|
||||||
|
BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, double>::value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test transform_iterator with function pointers
|
||||||
|
{
|
||||||
|
int x[N], y[N];
|
||||||
|
for (int k = 0; k < N; ++k)
|
||||||
|
x[k] = k;
|
||||||
|
std::copy(x, x + N, y);
|
||||||
|
|
||||||
|
for (int k2 = 0; k2 < N; ++k2)
|
||||||
|
x[k2] = x[k2] * 2;
|
||||||
|
|
||||||
|
boost::input_iterator_test(
|
||||||
|
boost::make_transform_iterator(y, mult_2), x[0], x[1]);
|
||||||
|
|
||||||
|
boost::input_iterator_test(
|
||||||
|
boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]);
|
||||||
|
|
||||||
|
boost::random_access_readable_iterator_test(
|
||||||
|
boost::make_transform_iterator(y, mult_2), N, x);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test transform_iterator as projection iterator
|
||||||
|
{
|
||||||
|
typedef std::pair<int, int> pair_t;
|
||||||
|
|
||||||
|
int x[N];
|
||||||
|
int y[N];
|
||||||
|
pair_t values[N];
|
||||||
|
|
||||||
|
for(int i = 0; i < N; ++i) {
|
||||||
|
|
||||||
|
x[i] = i;
|
||||||
|
y[i] = N - (i + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(
|
||||||
|
x
|
||||||
|
, x + N
|
||||||
|
, boost::make_transform_iterator((pair_t*)values, select_first())
|
||||||
|
);
|
||||||
|
|
||||||
|
std::copy(
|
||||||
|
y
|
||||||
|
, y + N
|
||||||
|
, boost::make_transform_iterator((pair_t*)values, select_second())
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::random_access_readable_iterator_test(
|
||||||
|
boost::make_transform_iterator((pair_t*)values, value_select_first())
|
||||||
|
, N
|
||||||
|
, x
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::random_access_readable_iterator_test(
|
||||||
|
boost::make_transform_iterator((pair_t*)values, const_select_first())
|
||||||
|
, N, x
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::constant_lvalue_iterator_test(
|
||||||
|
boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]);
|
||||||
|
|
||||||
|
boost::non_const_lvalue_iterator_test(
|
||||||
|
boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "test successful " << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
111
test/unit_tests.cpp
Normal file
111
test/unit_tests.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||||
|
// modify, sell and distribute this software is granted provided this
|
||||||
|
// copyright notice appears in all copies. This software is provided
|
||||||
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
|
// to its suitability for any purpose.
|
||||||
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
|
#include "static_assert_same.hpp"
|
||||||
|
|
||||||
|
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/detail/minimum_category.hpp>
|
||||||
|
|
||||||
|
struct X { int a; };
|
||||||
|
|
||||||
|
BOOST_TT_BROKEN_COMPILER_SPEC(X)
|
||||||
|
|
||||||
|
struct Xiter : boost::iterator_adaptor<Xiter,X*>
|
||||||
|
{
|
||||||
|
Xiter();
|
||||||
|
Xiter(X* p) : boost::iterator_adaptor<Xiter, X*>(p) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void take_xptr(X*) {}
|
||||||
|
void operator_arrow_test()
|
||||||
|
{
|
||||||
|
// check that the operator-> result is a pointer for lvalue iterators
|
||||||
|
X x;
|
||||||
|
take_xptr(Xiter(&x).operator->());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U, class Min>
|
||||||
|
struct static_assert_min_cat
|
||||||
|
: static_assert_same<
|
||||||
|
typename boost::detail::minimum_category<T,U>::type, Min
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
void category_test()
|
||||||
|
{
|
||||||
|
using namespace boost;
|
||||||
|
using namespace boost::detail;
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
!boost::is_convertible<
|
||||||
|
std::input_iterator_tag
|
||||||
|
, input_output_iterator_tag>::value));
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
!boost::is_convertible<
|
||||||
|
std::output_iterator_tag
|
||||||
|
, input_output_iterator_tag>::value));
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_convertible<
|
||||||
|
input_output_iterator_tag
|
||||||
|
, std::input_iterator_tag>::value));
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_convertible<
|
||||||
|
input_output_iterator_tag
|
||||||
|
, std::output_iterator_tag>::value));
|
||||||
|
|
||||||
|
#if 0 // This seems wrong; we're not advertising
|
||||||
|
// input_output_iterator_tag are we?
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_convertible<
|
||||||
|
std::forward_iterator_tag
|
||||||
|
, input_output_iterator_tag>::value));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int test = static_assert_min_cat<
|
||||||
|
std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag
|
||||||
|
>::value;
|
||||||
|
|
||||||
|
test = static_assert_min_cat<
|
||||||
|
input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag
|
||||||
|
>::value;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
test = static_assert_min_cat<
|
||||||
|
input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag
|
||||||
|
>::value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
test = static_assert_min_cat<
|
||||||
|
std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag
|
||||||
|
>::value;
|
||||||
|
|
||||||
|
test = static_assert_min_cat<
|
||||||
|
std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag
|
||||||
|
>::value;
|
||||||
|
|
||||||
|
#if 0 // This would be wrong: a random access iterator is not
|
||||||
|
// neccessarily writable, as is an output iterator.
|
||||||
|
test = static_assert_min_cat<
|
||||||
|
std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag
|
||||||
|
>::value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void)test;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
category_test();
|
||||||
|
operator_arrow_test();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
910
test/zip_iterator_test.cpp
Executable file
910
test/zip_iterator_test.cpp
Executable file
@ -0,0 +1,910 @@
|
|||||||
|
// (C) Copyright Dave Abrahams and Thomas Becker 2003. Permission to
|
||||||
|
// copy, use, modify, sell and distribute this software is granted
|
||||||
|
// provided this copyright notice appears in all copies. This software
|
||||||
|
// is provided "as is" without express or implied warranty, and with
|
||||||
|
// no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
|
||||||
|
// 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 <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
#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>
|
||||||
|
|
||||||
|
template <class It>
|
||||||
|
struct pure_traversal
|
||||||
|
: boost::detail::pure_traversal_tag<
|
||||||
|
typename boost::iterator_traversal<It>::type
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Das Main Funktion
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int main( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Make sure tuples are supported
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::cout << "Basic tuple support: "
|
||||||
|
<< std::flush;
|
||||||
|
|
||||||
|
typedef boost::tuples::tuple<int, double> mytuple;
|
||||||
|
mytuple t1;
|
||||||
|
boost::tuples::get<0>(t1) = 42;
|
||||||
|
boost::tuples::get<1>(t1) = 42.1;
|
||||||
|
|
||||||
|
if( 2 == boost::tuples::length<mytuple>::value &&
|
||||||
|
42 == boost::tuples::get<0>(t1) &&
|
||||||
|
42.1 == boost::tuples::get<1>(t1)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
++num_successful_tests;
|
||||||
|
std::cout << "OK" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++num_failed_tests = 0;
|
||||||
|
std::cout << "not OK" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Make sure iterator adaptor is supported
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::cout << "Basic iterator adaptor support: "
|
||||||
|
<< std::flush;
|
||||||
|
|
||||||
|
std::set<int> s;
|
||||||
|
s.insert(42);
|
||||||
|
s.insert(43);
|
||||||
|
s.insert(44);
|
||||||
|
|
||||||
|
typedef boost::transform_iterator<
|
||||||
|
std::binder1st<std::plus<int> >,
|
||||||
|
std::set<int>::iterator
|
||||||
|
>
|
||||||
|
add_seven_iterator;
|
||||||
|
|
||||||
|
typedef boost::transform_iterator<
|
||||||
|
std::binder1st<std::plus<int> >,
|
||||||
|
std::set<int>::const_iterator
|
||||||
|
>
|
||||||
|
const_add_seven_iterator;
|
||||||
|
|
||||||
|
add_seven_iterator set_run(s.begin(), std::bind1st(std::plus<int>(), 7));
|
||||||
|
add_seven_iterator set_end(s.end(), std::bind1st(std::plus<int>(), 7));
|
||||||
|
|
||||||
|
const_add_seven_iterator const_set_run(s.begin(), std::bind1st(std::plus<int>(), 7));
|
||||||
|
// set_run = const_set_run; // Error: can't convert from const to non-const
|
||||||
|
const_set_run = set_run;
|
||||||
|
|
||||||
|
if( 49 == *set_run &&
|
||||||
|
50 == *++set_run &&
|
||||||
|
51 == *++set_run &&
|
||||||
|
set_end == ++set_run &&
|
||||||
|
49 == *const_set_run &&
|
||||||
|
50 == *++const_set_run &&
|
||||||
|
51 == *++const_set_run &&
|
||||||
|
set_end == ++const_set_run
|
||||||
|
)
|
||||||
|
{
|
||||||
|
++num_successful_tests;
|
||||||
|
std::cout << "OK" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++num_failed_tests = 0;
|
||||||
|
std::cout << "not OK" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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);
|
||||||
|
//
|
||||||
|
|
||||||
|
boost::zip_iterator<
|
||||||
|
boost::tuples::tuple<
|
||||||
|
std::set<int>::iterator
|
||||||
|
, std::vector<double>::iterator
|
||||||
|
>
|
||||||
|
>
|
||||||
|
zip_it_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;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user