mirror of
https://github.com/boostorg/iterator.git
synced 2025-07-30 04:47:20 +02:00
This commit was manufactured by cvs2svn to create branch 'RC_1_31_0'.
[SVN r21650]
This commit is contained in:
40
doc/counting_iterator_eg.rst
Normal file
40
doc/counting_iterator_eg.rst
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
Example
|
||||
.......
|
||||
|
||||
This example fills an array with numbers and a second array with
|
||||
pointers into the first array, using ``counting_iterator`` for both
|
||||
tasks. Finally ``indirect_iterator`` is used to print out the numbers
|
||||
into the first array via indirection through the second array.
|
||||
|
||||
::
|
||||
|
||||
int N = 7;
|
||||
std::vector<int> numbers;
|
||||
typedef std::vector<int>::iterator n_iter;
|
||||
std::copy(boost::counting_iterator<int>(0),
|
||||
boost::counting_iterator<int>(N),
|
||||
std::back_inserter(numbers));
|
||||
|
||||
std::vector<std::vector<int>::iterator> pointers;
|
||||
std::copy(boost::make_counting_iterator(numbers.begin()),
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
|
||||
std::cout << "indirectly printing out the numbers from 0 to "
|
||||
<< N << std::endl;
|
||||
std::copy(boost::make_indirect_iterator(pointers.begin()),
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
The output is::
|
||||
|
||||
indirectly printing out the numbers from 0 to 7
|
||||
0 1 2 3 4 5 6
|
||||
|
||||
The source code for this example can be found `here`__.
|
||||
|
||||
__ ../example/counting_iterator_example.cpp
|
||||
|
69
doc/filter_iterator_eg.rst
Normal file
69
doc/filter_iterator_eg.rst
Normal file
@ -0,0 +1,69 @@
|
||||
|
||||
Example
|
||||
.......
|
||||
|
||||
This example uses ``filter_iterator`` and then
|
||||
``make_filter_iterator`` to output only the positive integers from an
|
||||
array of integers. Then ``make_filter_iterator`` is is used to output
|
||||
the integers greater than ``-2``.
|
||||
|
||||
::
|
||||
|
||||
struct is_positive_number {
|
||||
bool operator()(int x) { return 0 < x; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers_)/sizeof(int);
|
||||
|
||||
typedef int* base_iterator;
|
||||
base_iterator numbers(numbers_);
|
||||
|
||||
// Example using filter_iterator
|
||||
typedef boost::filter_iterator<is_positive_number, base_iterator>
|
||||
FilterIter;
|
||||
|
||||
is_positive_number predicate;
|
||||
FilterIter filter_iter_first(predicate, numbers, numbers + N);
|
||||
FilterIter filter_iter_last(predicate, numbers + N, numbers + N);
|
||||
|
||||
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Another example using make_filter_iterator()
|
||||
std::copy(
|
||||
boost::make_filter_iterator(
|
||||
std::bind2nd(std::greater<int>(), -2)
|
||||
, numbers, numbers + N)
|
||||
|
||||
, boost::make_filter_iterator(
|
||||
std::bind2nd(std::greater<int>(), -2)
|
||||
, numbers + N, numbers + N)
|
||||
|
||||
, std::ostream_iterator<int>(std::cout, " ")
|
||||
);
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
||||
|
||||
|
||||
The output is::
|
||||
|
||||
4 5 8
|
||||
4 5 8
|
||||
0 -1 4 5 8
|
||||
|
||||
|
||||
The source code for this example can be found `here`__.
|
||||
|
||||
__ ../example/filter_iterator_example.cpp
|
35
doc/function_output_iterator_eg.rst
Normal file
35
doc/function_output_iterator_eg.rst
Normal file
@ -0,0 +1,35 @@
|
||||
Example
|
||||
.......
|
||||
|
||||
::
|
||||
|
||||
struct string_appender
|
||||
{
|
||||
string_appender(std::string& s)
|
||||
: m_str(&s)
|
||||
{}
|
||||
|
||||
void operator()(const std::string& x) const
|
||||
{
|
||||
*m_str += x;
|
||||
}
|
||||
|
||||
std::string* m_str;
|
||||
};
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::vector<std::string> x;
|
||||
x.push_back("hello");
|
||||
x.push_back(" ");
|
||||
x.push_back("world");
|
||||
x.push_back("!");
|
||||
|
||||
std::string s = "";
|
||||
std::copy(x.begin(), x.end(),
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
|
||||
std::cout << s << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
69
doc/indirect_iterator_eg.rst
Normal file
69
doc/indirect_iterator_eg.rst
Normal file
@ -0,0 +1,69 @@
|
||||
Example
|
||||
.......
|
||||
|
||||
This example prints an array of characters, using
|
||||
``indirect_iterator`` to access the array of characters through an
|
||||
array of pointers. Next ``indirect_iterator`` is used with the
|
||||
``transform`` algorithm to copy the characters (incremented by one) to
|
||||
another array. A constant indirect iterator is used for the source and
|
||||
a mutable indirect iterator is used for the destination. The last part
|
||||
of the example prints the original array of characters, but this time
|
||||
using the ``make_indirect_iterator`` helper function.
|
||||
|
||||
|
||||
::
|
||||
|
||||
char characters[] = "abcdefg";
|
||||
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
|
||||
char* pointers_to_chars[N]; // at the end.
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_chars[i] = &characters[i];
|
||||
|
||||
// Example of using indirect_iterator
|
||||
|
||||
boost::indirect_iterator<char**, char>
|
||||
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of making mutable and constant indirect iterators
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int j = 0; j < N; ++j)
|
||||
pointers_to_mutable_chars[j] = &mutable_characters[j];
|
||||
|
||||
boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars),
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of using make_indirect_iterator()
|
||||
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
The output is::
|
||||
|
||||
a,b,c,d,e,f,g,
|
||||
b,c,d,e,f,g,h,
|
||||
a,b,c,d,e,f,g,
|
||||
|
||||
|
||||
The source code for this example can be found `here`__.
|
||||
|
||||
__ ../example/indirect_iterator_example.cpp
|
||||
|
232
doc/interoperability-revisited.rst
Executable file
232
doc/interoperability-revisited.rst
Executable file
@ -0,0 +1,232 @@
|
||||
++++++++++++++++++++++++++++
|
||||
Interoperability Revisited
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
:date: $Date$
|
||||
:copyright: Copyright Thomas Witt 2004.
|
||||
|
||||
|
||||
Problem
|
||||
=======
|
||||
|
||||
The current iterator_facade specification makes it unneccessarily tedious to
|
||||
implement interoperable iterators.
|
||||
|
||||
In the following text a simplified example of the current iterator_facade specification is used to
|
||||
illustrate the problem.
|
||||
|
||||
In the current specification binary operators are implemented in the following way:
|
||||
|
||||
template <class Derived>
|
||||
struct Facade
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, T2>
|
||||
struct is_interoperable :
|
||||
or_<
|
||||
is_convertible<T1, T2>
|
||||
, is_convertible<T2, T1>
|
||||
>
|
||||
{};
|
||||
|
||||
template<
|
||||
class Derived1
|
||||
, class Derived2
|
||||
>
|
||||
enable_if<is_interoperable<Derived1, Derived2>, bool> operator==(
|
||||
Derived1 const& lhs
|
||||
, Derived2 const& rhs
|
||||
)
|
||||
{
|
||||
return static_cast<Derived1 const&>(lhs).equal_to(static_cast<Derived2 const&(rhs));
|
||||
}
|
||||
|
||||
The problem with this is that operator== always forwards to Derived1::equal_to. The net effect is that the
|
||||
following "obvious" implementation of to interoperable types does not quite work.
|
||||
|
||||
struct Mutable : Facade<Mutable>
|
||||
{
|
||||
bool equal_to(Mutable const&);
|
||||
};
|
||||
|
||||
struct Constant : Facade<Constant>
|
||||
{
|
||||
Constant();
|
||||
Constant(Constant const&);
|
||||
Constant(Mutable const&);
|
||||
|
||||
...
|
||||
|
||||
bool equal_to(Constant const&);
|
||||
};
|
||||
|
||||
Constant c;
|
||||
Mutable m;
|
||||
|
||||
c == m; // ok, dispatched to Constant::equal_to
|
||||
m == c; // !! error, dispatched to Mutable::equal_to
|
||||
|
||||
Instead the following "slightly" more complicated implementation is neccessary
|
||||
|
||||
struct Mutable : Facade<Mutable>
|
||||
{
|
||||
template <class T>
|
||||
enable_if<is_convertible<Mutable, T> || is_convertible<T, Mutable>, bool>::type equal_to(T const&);
|
||||
};
|
||||
|
||||
struct Constant : Tag<Constant>
|
||||
{
|
||||
Constant();
|
||||
Constant(Constant const&);
|
||||
Constant(Mutable const&);
|
||||
|
||||
template <class T>
|
||||
enable_if<is_convertible<Constant, T> || is_convertible<T, Constant>, bool>::type equal_to(T const&);
|
||||
};
|
||||
|
||||
Beside the fact that the code is significantly more complex to understand and to teach there is
|
||||
a major design problem lurking here. Note that in both types equal_to is a function template with
|
||||
an unconstrained argument T. This is neccessary so that further types can be made interoperable with
|
||||
Mutable or Constant. Would Mutable be defined as
|
||||
|
||||
struct Mutable : Facade<Mutable>
|
||||
{
|
||||
bool equal_to(Mutable const&);
|
||||
bool equal_to(Constant const&);
|
||||
};
|
||||
|
||||
Constant and Mutable would still be interoperable but no further interoperable could be added
|
||||
without changing Mutable. Even if this would be considered acceptable the current specification forces
|
||||
a two way dependency between interoperable types. Note in the templated equal_to case this dependency
|
||||
is implicitly created when specializing equal_to.
|
||||
|
||||
Solution
|
||||
========
|
||||
|
||||
The two way dependency can be avoided by enabling type conversion in the binary operator
|
||||
implementation. Note that this is the usual way interoperability betwween types is achieved
|
||||
for binary operators and one reason why binary operators are usually implemented as non-members.
|
||||
|
||||
A simple implementation of this strategy would look like this
|
||||
|
||||
template<
|
||||
class T1
|
||||
, class T2
|
||||
>
|
||||
struct interoperable_base :
|
||||
if_<
|
||||
is_convertible<
|
||||
T2
|
||||
, T1
|
||||
>
|
||||
, T1
|
||||
, T2>
|
||||
{};
|
||||
|
||||
|
||||
template<
|
||||
class Derived1
|
||||
, class Derived2
|
||||
>
|
||||
enable_if<is_interoperable<Derived1, Derived2>, bool> operator==(
|
||||
Derived1 const& lhs
|
||||
, Derived2 const& rhs
|
||||
)
|
||||
{
|
||||
typedef interoperable_base<
|
||||
Derived1
|
||||
, Derived2
|
||||
>::type Base;
|
||||
|
||||
return static_cast<Base const&>(lhs).equal_to(static_cast<Derived2 const&(rhs));
|
||||
}
|
||||
|
||||
This way our original simple and "obvious" implementation would work again.
|
||||
|
||||
c == m; // ok, dispatched to Constant::equal_to
|
||||
m == c; // ok, dispatched to Constant::equal_to, m converted to Constant
|
||||
|
||||
The backdraw of this approach is that a possibly costly conversion of iterator objects
|
||||
is forced on the user even in cases where direct comparison could be implemented
|
||||
in a much more efficient way. This problem arises especially for iterator_adaptor
|
||||
specializations and can be significantly slow down the iteration over ranges. Given the fact
|
||||
that iteration is a very basic operation this possible performance degradation is not
|
||||
acceptable.
|
||||
|
||||
Luckily whe can have our cake and eat it by a slightly more clever implementation of the binary
|
||||
operators.
|
||||
|
||||
template<
|
||||
class Derived1
|
||||
, class Derived2
|
||||
>
|
||||
enable_if<is_convertible<Derived2, Derived1>, bool> operator==(
|
||||
Derived1 const& lhs
|
||||
, Derived2 const& rhs
|
||||
)
|
||||
{
|
||||
return static_cast<Derived1 const&>(lhs).equal_to(static_cast<Derived2 const&(rhs));
|
||||
}
|
||||
|
||||
template<
|
||||
class Derived1
|
||||
, class Derived2
|
||||
>
|
||||
enable_if<is_convertible<Derived1, Derived2>, bool> operator==(
|
||||
Derived1 const& lhs
|
||||
, Derived2 const& rhs
|
||||
)
|
||||
{
|
||||
return static_cast<Derived2 const&>(rhs).equal_to(static_cast<Derived1 const&(lhs));
|
||||
}
|
||||
|
||||
Given our simple and obvious definition of Mutable and Constant nothing has changed yet.
|
||||
|
||||
c == m; // ok, dispatched to Constant::equal_to, m converted to Constant
|
||||
m == c; // ok, dispatched to Constant::equal_to, m converted to Constant
|
||||
|
||||
But now the user can avoid the type conversion by supplying the appropriate overload in Constant
|
||||
|
||||
struct Constant : Facade<Constant>
|
||||
{
|
||||
Constant();
|
||||
Constant(Constant const&);
|
||||
Constant(Mutable const&);
|
||||
|
||||
...
|
||||
|
||||
bool equal_to(Constant const&);
|
||||
bool equal_to(Mutable const&);
|
||||
};
|
||||
|
||||
c == m; // ok, dispatched to Constant::equal_to(Mutable const&), no conversion
|
||||
m == c; // ok, dispatched to Constant::equal_to(Mutable const&), no conversion
|
||||
|
||||
This definition of operator== introduces a possible ambiguity when both types are convertible
|
||||
to each other. I don't think this is a problem as this behaviour is the same with concrete types.
|
||||
I.e.
|
||||
|
||||
struct A {};
|
||||
|
||||
bool operator==(A, A);
|
||||
|
||||
struct B { B(A); };
|
||||
|
||||
bool operator==(B, B);
|
||||
|
||||
A a;
|
||||
B b(a);
|
||||
|
||||
a == b; // error, ambiguous overload
|
||||
|
||||
Effect
|
||||
======
|
||||
|
||||
Iterator implementations using iterator_facade look exactly as if they were
|
||||
"hand-implemented" (I am working on better wording).
|
||||
|
||||
a) Less burden for the user
|
||||
|
||||
b) The definition (standardese) of specialized adpters might be easier
|
||||
(This has to be proved yet)
|
9
doc/make_counting_iterator.rst
Executable file
9
doc/make_counting_iterator.rst
Executable file
@ -0,0 +1,9 @@
|
||||
|
||||
::
|
||||
|
||||
template <class Incrementable>
|
||||
counting_iterator<Incrementable> make_counting_iterator(Incrementable x);
|
||||
|
||||
:Returns: An instance of ``counting_iterator<Incrementable>``
|
||||
with ``current`` constructed from ``x``.
|
||||
|
9
doc/make_reverse_iterator.rst
Normal file
9
doc/make_reverse_iterator.rst
Normal file
@ -0,0 +1,9 @@
|
||||
::
|
||||
|
||||
template <class BidirectionalIterator>
|
||||
reverse_iterator<BidirectionalIterator>n
|
||||
make_reverse_iterator(BidirectionalIterator x);
|
||||
|
||||
:Returns: An instance of ``reverse_iterator<BidirectionalIterator>``
|
||||
with a ``current`` constructed from ``x``.
|
||||
|
19
doc/make_transform_iterator.rst
Executable file
19
doc/make_transform_iterator.rst
Executable file
@ -0,0 +1,19 @@
|
||||
::
|
||||
|
||||
template <class UnaryFunction, class Iterator>
|
||||
transform_iterator<UnaryFunction, Iterator>
|
||||
make_transform_iterator(Iterator it, UnaryFunction fun);
|
||||
|
||||
:Returns: An instance of ``transform_iterator<UnaryFunction, Iterator>`` with ``m_f``
|
||||
initialized to ``f`` and ``m_iterator`` initialized to ``x``.
|
||||
|
||||
|
||||
|
||||
::
|
||||
|
||||
template <class UnaryFunction, class Iterator>
|
||||
transform_iterator<UnaryFunction, Iterator>
|
||||
make_transform_iterator(Iterator it);
|
||||
|
||||
:Returns: An instance of ``transform_iterator<UnaryFunction, Iterator>`` with ``m_f``
|
||||
default constructed and ``m_iterator`` initialized to ``x``.
|
67
doc/permutation_iterator_eg.rst
Normal file
67
doc/permutation_iterator_eg.rst
Normal file
@ -0,0 +1,67 @@
|
||||
::
|
||||
|
||||
using namespace boost;
|
||||
int i = 0;
|
||||
|
||||
typedef std::vector< int > element_range_type;
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
static const int element_range_size = 10;
|
||||
static const int index_size = 4;
|
||||
|
||||
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 permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type;
|
||||
permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type it = begin;
|
||||
permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
std::cout << "The original range is : ";
|
||||
std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The reindexing scheme is : ";
|
||||
std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The permutated range is : ";
|
||||
std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Elements at even indices in the permutation : ";
|
||||
it = begin;
|
||||
for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Permutation backwards : ";
|
||||
it = begin + (index_size);
|
||||
assert( it != begin );
|
||||
for( ; it-- != begin ; ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Iterate backward with stride 2 : ";
|
||||
it = begin + (index_size - 1);
|
||||
for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
|
||||
The output is::
|
||||
|
||||
The original range is : 0 1 2 3 4 5 6 7 8 9
|
||||
The reindexing scheme is : 9 8 7 6
|
||||
The permutated range is : 9 8 7 6
|
||||
Elements at even indices in the permutation : 9 7
|
||||
Permutation backwards : 6 7 8 9
|
||||
Iterate backward with stride 2 : 6 8
|
||||
|
||||
|
||||
The source code for this example can be found `here`__.
|
||||
|
||||
__ ../example/permutation_iterator_example.cpp
|
42
doc/reverse_iterator_eg.rst
Normal file
42
doc/reverse_iterator_eg.rst
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
Example
|
||||
.......
|
||||
|
||||
The following example prints an array of characters in reverse order
|
||||
using ``reverse_iterator``.
|
||||
|
||||
::
|
||||
|
||||
char letters_[] = "hello world!";
|
||||
const int N = sizeof(letters_)/sizeof(char) - 1;
|
||||
typedef char* base_iterator;
|
||||
base_iterator letters(letters_);
|
||||
std::cout << "original sequence of letters:\t\t\t" << letters_ << std::endl;
|
||||
|
||||
boost::reverse_iterator<base_iterator>
|
||||
reverse_letters_first(letters + N),
|
||||
reverse_letters_last(letters);
|
||||
|
||||
std::cout << "sequence in reverse order:\t\t\t";
|
||||
std::copy(reverse_letters_first, reverse_letters_last,
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "sequence in double-reversed (normal) order:\t";
|
||||
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
|
||||
The output is::
|
||||
|
||||
original sequence of letters: hello world!
|
||||
sequence in reverse order: !dlrow olleh
|
||||
sequence in double-reversed (normal) order: hello world!
|
||||
|
||||
|
||||
The source code for this example can be found `here`__.
|
||||
|
||||
__ ../example/reverse_iterator_example.cpp
|
42
doc/transform_iterator_eg.rst
Executable file
42
doc/transform_iterator_eg.rst
Executable file
@ -0,0 +1,42 @@
|
||||
Example
|
||||
.......
|
||||
|
||||
This is a simple example of using the transform_iterators class to
|
||||
generate iterators that multiply (or add to) the value returned by
|
||||
dereferencing the iterator. It would be cooler to use lambda library
|
||||
in this example.
|
||||
|
||||
::
|
||||
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const int N = sizeof(x)/sizeof(int);
|
||||
|
||||
typedef boost::binder1st< std::multiplies<int> > Function;
|
||||
typedef boost::transform_iterator<Function, int*> doubling_iterator;
|
||||
|
||||
doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
|
||||
i_end(x + N, boost::bind1st(std::multiplies<int>(), 2));
|
||||
|
||||
std::cout << "multiplying the array by 2:" << std::endl;
|
||||
while (i != i_end)
|
||||
std::cout << *i++ << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "adding 4 to each element in the array:" << std::endl;
|
||||
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
|
||||
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
The output is::
|
||||
|
||||
multiplying the array by 2:
|
||||
2 4 6 8 10 12 14 16
|
||||
adding 4 to each element in the array:
|
||||
5 6 7 8 9 10 11 12
|
||||
|
||||
|
||||
The source code for this example can be found `here`__.
|
||||
|
||||
__ ../example/transform_iterator_example.cpp
|
54
example/counting_iterator_example.cpp
Normal file
54
example/counting_iterator_example.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// (C) Copyright Jeremy Siek 2000-2004.
|
||||
// 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 <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
#include <boost/cstdlib.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
// Example of using counting_iterator
|
||||
std::cout << "counting from 0 to 4:" << std::endl;
|
||||
boost::counting_iterator<int> first(0), last(4);
|
||||
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using counting iterator to create an array of pointers.
|
||||
int N = 7;
|
||||
std::vector<int> numbers;
|
||||
typedef std::vector<int>::iterator n_iter;
|
||||
// Fill "numbers" array with [0,N)
|
||||
std::copy(
|
||||
boost::counting_iterator<int>(0)
|
||||
, boost::counting_iterator<int>(N)
|
||||
, std::back_inserter(numbers));
|
||||
|
||||
std::vector<std::vector<int>::iterator> pointers;
|
||||
|
||||
// Use counting iterator to fill in the array of pointers.
|
||||
// causes an ICE with MSVC6
|
||||
std::copy(boost::make_counting_iterator(numbers.begin()),
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
|
||||
// Use indirect iterator to print out numbers by accessing
|
||||
// them through the array of pointers.
|
||||
std::cout << "indirectly printing out the numbers from 0 to "
|
||||
<< N << std::endl;
|
||||
std::copy(boost::make_indirect_iterator(pointers.begin()),
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
60
example/filter_iterator_example.cpp
Normal file
60
example/filter_iterator_example.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// (C) Copyright Jeremy Siek 1999-2004.
|
||||
// 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 <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
#include <boost/cstdlib.hpp> // for exit_success
|
||||
|
||||
struct is_positive_number {
|
||||
bool operator()(int x) { return 0 < x; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers_)/sizeof(int);
|
||||
|
||||
typedef int* base_iterator;
|
||||
base_iterator numbers(numbers_);
|
||||
|
||||
// Example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example using filter_iterator
|
||||
typedef boost::filter_iterator<is_positive_number, base_iterator>
|
||||
FilterIter;
|
||||
|
||||
is_positive_number predicate;
|
||||
FilterIter filter_iter_first(predicate, numbers, numbers + N);
|
||||
FilterIter filter_iter_last(predicate, numbers + N, numbers + N);
|
||||
|
||||
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Another example using make_filter_iterator()
|
||||
std::copy(
|
||||
boost::make_filter_iterator(
|
||||
std::bind2nd(std::greater<int>(), -2)
|
||||
, numbers, numbers + N)
|
||||
|
||||
, boost::make_filter_iterator(
|
||||
std::bind2nd(std::greater<int>(), -2)
|
||||
, numbers + N, numbers + N)
|
||||
|
||||
, std::ostream_iterator<int>(std::cout, " ")
|
||||
);
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
48
example/function_output_iterator_example.cpp
Normal file
48
example/function_output_iterator_example.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
// (C) Copyright Jeremy Siek 2001-2004.
|
||||
// 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:
|
||||
|
||||
// 27 Feb 2001 Jeremy Siek
|
||||
// Initial checkin.
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
|
||||
struct string_appender
|
||||
{
|
||||
string_appender(std::string& s)
|
||||
: m_str(&s)
|
||||
{}
|
||||
|
||||
void operator()(const std::string& x) const
|
||||
{
|
||||
*m_str += x;
|
||||
}
|
||||
|
||||
std::string* m_str;
|
||||
};
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::vector<std::string> x;
|
||||
x.push_back("hello");
|
||||
x.push_back(" ");
|
||||
x.push_back("world");
|
||||
x.push_back("!");
|
||||
|
||||
std::string s = "";
|
||||
std::copy(x.begin(), x.end(),
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
|
||||
std::cout << s << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
61
example/indirect_iterator_example.cpp
Normal file
61
example/indirect_iterator_example.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
// (C) Copyright Jeremy Siek 2000-2004.
|
||||
// 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 <vector>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char characters[] = "abcdefg";
|
||||
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
|
||||
char* pointers_to_chars[N]; // at the end.
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_chars[i] = &characters[i];
|
||||
|
||||
// Example of using indirect_iterator
|
||||
|
||||
boost::indirect_iterator<char**, char>
|
||||
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of making mutable and constant indirect iterators
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int j = 0; j < N; ++j)
|
||||
pointers_to_mutable_chars[j] = &mutable_characters[j];
|
||||
|
||||
boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars),
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of using make_indirect_iterator()
|
||||
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
60
example/node.hpp
Executable file
60
example/node.hpp
Executable file
@ -0,0 +1,60 @@
|
||||
// Copyright David Abrahams 2004. 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 NODE_DWA2004110_HPP
|
||||
# define NODE_DWA2004110_HPP
|
||||
|
||||
# include <iostream>
|
||||
|
||||
// Polymorphic list node base class
|
||||
|
||||
struct node_base
|
||||
{
|
||||
node_base() : m_next(0) {}
|
||||
|
||||
virtual ~node_base()
|
||||
{
|
||||
delete m_next;
|
||||
}
|
||||
|
||||
node_base* next() const
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
virtual void print(std::ostream& s) const = 0;
|
||||
virtual void double_me() = 0;
|
||||
|
||||
void append(node_base* p)
|
||||
{
|
||||
if (m_next)
|
||||
m_next->append(p);
|
||||
else
|
||||
m_next = p;
|
||||
}
|
||||
|
||||
private:
|
||||
node_base* m_next;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, node_base const& n)
|
||||
{
|
||||
n.print(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct node : node_base
|
||||
{
|
||||
node(T x)
|
||||
: m_value(x)
|
||||
{}
|
||||
|
||||
void print(std::ostream& s) const { s << this->m_value; }
|
||||
void double_me() { m_value += m_value; }
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
};
|
||||
|
||||
#endif // NODE_DWA2004110_HPP
|
34
example/node_iterator1.cpp
Executable file
34
example/node_iterator1.cpp
Executable file
@ -0,0 +1,34 @@
|
||||
// Copyright David Abrahams 2004. 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 "node_iterator1.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::auto_ptr<node<int> > nodes(new node<int>(42));
|
||||
nodes->append(new node<std::string>(" is greater than "));
|
||||
nodes->append(new node<int>(13));
|
||||
|
||||
std::copy(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, " ")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
|
||||
std::for_each(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, std::mem_fun_ref(&node_base::double_me)
|
||||
);
|
||||
|
||||
std::copy(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, "/")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
}
|
42
example/node_iterator1.hpp
Executable file
42
example/node_iterator1.hpp
Executable file
@ -0,0 +1,42 @@
|
||||
// Copyright David Abrahams 2004. 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 NODE_ITERATOR1_DWA2004110_HPP
|
||||
# define NODE_ITERATOR1_DWA2004110_HPP
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
class node_iterator
|
||||
: public boost::iterator_facade<
|
||||
node_iterator
|
||||
, node_base
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
node_iterator()
|
||||
: m_node(0)
|
||||
{}
|
||||
|
||||
explicit node_iterator(node_base* p)
|
||||
: m_node(p)
|
||||
{}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
void increment()
|
||||
{ m_node = m_node->next(); }
|
||||
|
||||
bool equal(node_iterator const& other) const
|
||||
{ return this->m_node == other.m_node; }
|
||||
|
||||
node_base& dereference() const
|
||||
{ return *m_node; }
|
||||
|
||||
node_base* m_node;
|
||||
};
|
||||
|
||||
|
||||
#endif // NODE_ITERATOR1_DWA2004110_HPP
|
43
example/node_iterator2.cpp
Executable file
43
example/node_iterator2.cpp
Executable file
@ -0,0 +1,43 @@
|
||||
// Copyright David Abrahams 2004. 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 "node_iterator2.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/mem_fn.hpp>
|
||||
#include <cassert>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::auto_ptr<node<int> > nodes(new node<int>(42));
|
||||
nodes->append(new node<std::string>(" is greater than "));
|
||||
nodes->append(new node<int>(13));
|
||||
|
||||
// Check interoperability
|
||||
assert(node_iterator(nodes.get()) == node_const_iterator(nodes.get()));
|
||||
assert(node_const_iterator(nodes.get()) == node_iterator(nodes.get()));
|
||||
|
||||
assert(node_iterator(nodes.get()) != node_const_iterator());
|
||||
assert(node_const_iterator(nodes.get()) != node_iterator());
|
||||
|
||||
std::copy(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, " ")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
|
||||
std::for_each(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, boost::mem_fn(&node_base::double_me)
|
||||
);
|
||||
|
||||
std::copy(
|
||||
node_const_iterator(nodes.get()), node_const_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, "/")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
58
example/node_iterator2.hpp
Executable file
58
example/node_iterator2.hpp
Executable file
@ -0,0 +1,58 @@
|
||||
// Copyright David Abrahams 2004. 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 NODE_ITERATOR2_DWA2004110_HPP
|
||||
# define NODE_ITERATOR2_DWA2004110_HPP
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_adaptor.hpp>
|
||||
|
||||
# ifndef BOOST_NO_SFINAE
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# endif
|
||||
|
||||
template <class Value>
|
||||
class node_iter
|
||||
: public boost::iterator_adaptor<
|
||||
node_iter<Value> // Derived
|
||||
, Value* // Base
|
||||
, boost::use_default // Value
|
||||
, boost::forward_traversal_tag // CategoryOrTraversal
|
||||
>
|
||||
{
|
||||
private:
|
||||
struct enabler {}; // a private type avoids misuse
|
||||
|
||||
typedef boost::iterator_adaptor<
|
||||
node_iter<Value>, Value*, boost::use_default, boost::forward_traversal_tag
|
||||
> super_t;
|
||||
|
||||
public:
|
||||
node_iter()
|
||||
: super_t(0) {}
|
||||
|
||||
explicit node_iter(Value* p)
|
||||
: super_t(p) {}
|
||||
|
||||
template <class OtherValue>
|
||||
node_iter(
|
||||
node_iter<OtherValue> const& other
|
||||
# ifndef BOOST_NO_SFINAE
|
||||
, typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,Value*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
# endif
|
||||
)
|
||||
: m_node(other.m_node) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
void increment() { m_node = m_node->next(); }
|
||||
};
|
||||
|
||||
typedef node_iter<node_base> node_iterator;
|
||||
typedef node_iter<node_base const> node_const_iterator;
|
||||
|
||||
#endif // NODE_ITERATOR2_DWA2004110_HPP
|
43
example/node_iterator3.cpp
Executable file
43
example/node_iterator3.cpp
Executable file
@ -0,0 +1,43 @@
|
||||
// Copyright David Abrahams 2004. 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 "node_iterator3.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/mem_fn.hpp>
|
||||
#include <cassert>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::auto_ptr<node<int> > nodes(new node<int>(42));
|
||||
nodes->append(new node<std::string>(" is greater than "));
|
||||
nodes->append(new node<int>(13));
|
||||
|
||||
// Check interoperability
|
||||
assert(node_iterator(nodes.get()) == node_const_iterator(nodes.get()));
|
||||
assert(node_const_iterator(nodes.get()) == node_iterator(nodes.get()));
|
||||
|
||||
assert(node_iterator(nodes.get()) != node_const_iterator());
|
||||
assert(node_const_iterator(nodes.get()) != node_iterator());
|
||||
|
||||
std::copy(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, " ")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
|
||||
std::for_each(
|
||||
node_iterator(nodes.get()), node_iterator()
|
||||
, boost::mem_fn(&node_base::double_me)
|
||||
);
|
||||
|
||||
std::copy(
|
||||
node_const_iterator(nodes.get()), node_const_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, "/")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
58
example/node_iterator3.hpp
Executable file
58
example/node_iterator3.hpp
Executable file
@ -0,0 +1,58 @@
|
||||
// Copyright David Abrahams 2004. 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 NODE_ITERATOR3_DWA2004110_HPP
|
||||
# define NODE_ITERATOR3_DWA2004110_HPP
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_adaptor.hpp>
|
||||
|
||||
# ifndef BOOST_NO_SFINAE
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# endif
|
||||
|
||||
template <class Value>
|
||||
class node_iter
|
||||
: public boost::iterator_adaptor<
|
||||
node_iter<Value> // Derived
|
||||
, Value* // Base
|
||||
, boost::use_default // Value
|
||||
, boost::forward_traversal_tag // CategoryOrTraversal
|
||||
>
|
||||
{
|
||||
private:
|
||||
struct enabler {}; // a private type avoids misuse
|
||||
|
||||
typedef boost::iterator_adaptor<
|
||||
node_iter<Value>, Value*, boost::use_default, boost::forward_traversal_tag
|
||||
> super_t;
|
||||
|
||||
public:
|
||||
node_iter()
|
||||
: super_t(0) {}
|
||||
|
||||
explicit node_iter(Value* p)
|
||||
: super_t(p) {}
|
||||
|
||||
template <class OtherValue>
|
||||
node_iter(
|
||||
node_iter<OtherValue> const& other
|
||||
# ifndef BOOST_NO_SFINAE
|
||||
, typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,Value*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
# endif
|
||||
)
|
||||
: m_node(other.m_node) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
void increment() { this->base_reference() = this->base()->next(); }
|
||||
};
|
||||
|
||||
typedef node_iter<node_base> node_iterator;
|
||||
typedef node_iter<node_base const> node_const_iterator;
|
||||
|
||||
#endif // NODE_ITERATOR3_DWA2004110_HPP
|
61
example/permutation_iterator_example.cpp
Normal file
61
example/permutation_iterator_example.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/iterator/permutation_iterator.hpp>
|
||||
#include <boost/cstdlib.hpp>
|
||||
|
||||
|
||||
int main() {
|
||||
using namespace boost;
|
||||
int i = 0;
|
||||
|
||||
typedef std::vector< int > element_range_type;
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
static const int element_range_size = 10;
|
||||
static const int index_size = 4;
|
||||
|
||||
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 permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type;
|
||||
permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type it = begin;
|
||||
permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
std::cout << "The original range is : ";
|
||||
std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The reindexing scheme is : ";
|
||||
std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The permutated range is : ";
|
||||
std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Elements at even indices in the permutation : ";
|
||||
it = begin;
|
||||
for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Permutation backwards : ";
|
||||
it = begin + (index_size);
|
||||
assert( it != begin );
|
||||
for( ; it-- != begin ; ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Iterate backward with stride 2 : ";
|
||||
it = begin + (index_size - 1);
|
||||
for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
43
example/reverse_iterator_example.cpp
Normal file
43
example/reverse_iterator_example.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
// (C) Copyright Jeremy Siek 2000-2004.
|
||||
// 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 <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/cstdlib.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char letters_[] = "hello world!";
|
||||
const int N = sizeof(letters_)/sizeof(char) - 1;
|
||||
typedef char* base_iterator;
|
||||
base_iterator letters(letters_);
|
||||
|
||||
std::cout << "original sequence of letters:\t\t\t"
|
||||
<< letters_ << std::endl;
|
||||
|
||||
// Use reverse_iterator to print a sequence of letters in reverse
|
||||
// order.
|
||||
|
||||
boost::reverse_iterator<base_iterator>
|
||||
reverse_letters_first(letters + N),
|
||||
reverse_letters_last(letters);
|
||||
|
||||
std::cout << "sequence in reverse order:\t\t\t";
|
||||
std::copy(reverse_letters_first, reverse_letters_last,
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "sequence in double-reversed (normal) order:\t";
|
||||
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
78
example/transform_iterator_example.cpp
Normal file
78
example/transform_iterator_example.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
// (C) Copyright Jeremy Siek 2000-2004.
|
||||
// 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 <functional>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
// What a bummer. We can't use std::binder1st with transform iterator
|
||||
// because it does not have a default constructor. Here's a version
|
||||
// that does.
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Operation>
|
||||
class binder1st
|
||||
: public std::unary_function<typename Operation::second_argument_type,
|
||||
typename Operation::result_type> {
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st() { } // this had to be added!
|
||||
binder1st(const Operation& x,
|
||||
const typename Operation::first_argument_type& y)
|
||||
: op(x), value(y) {}
|
||||
typename Operation::result_type
|
||||
operator()(const typename Operation::second_argument_type& x) const {
|
||||
return op(value, x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Operation, class T>
|
||||
inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
|
||||
typedef typename Operation::first_argument_type arg1_type;
|
||||
return binder1st<Operation>(op, arg1_type(x));
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
int
|
||||
main(int, char*[])
|
||||
{
|
||||
// This is a simple example of using the transform_iterators class to
|
||||
// generate iterators that multiply the value returned by dereferencing
|
||||
// the iterator. In this case we are multiplying by 2.
|
||||
// Would be cooler to use lambda library in this example.
|
||||
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const int N = sizeof(x)/sizeof(int);
|
||||
|
||||
typedef boost::binder1st< std::multiplies<int> > Function;
|
||||
typedef boost::transform_iterator<Function, int*> doubling_iterator;
|
||||
|
||||
doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
|
||||
i_end(x + N, boost::bind1st(std::multiplies<int>(), 2));
|
||||
|
||||
std::cout << "multiplying the array by 2:" << std::endl;
|
||||
while (i != i_end)
|
||||
std::cout << *i++ << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "adding 4 to each element in the array:" << std::endl;
|
||||
|
||||
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
|
||||
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
72
test/pointee.cpp
Executable file
72
test/pointee.cpp
Executable file
@ -0,0 +1,72 @@
|
||||
// Copyright David Abrahams 2004. 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 <boost/pointee.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include "static_assert_same.hpp"
|
||||
#include <memory>
|
||||
#include <list>
|
||||
|
||||
template <class T, class Ref>
|
||||
struct proxy_ptr
|
||||
{
|
||||
typedef T element_type;
|
||||
struct proxy
|
||||
{
|
||||
operator Ref() const;
|
||||
};
|
||||
proxy operator*() const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct proxy_ref_ptr : proxy_ptr<T,T&>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct proxy_value_ptr : proxy_ptr<T,T>
|
||||
{
|
||||
typedef typename boost::add_const<T>::type element_type;
|
||||
};
|
||||
|
||||
struct X {
|
||||
template <class T> X(T const&);
|
||||
template <class T> operator T&() const;
|
||||
};
|
||||
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(X)
|
||||
|
||||
int main()
|
||||
{
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_ref_ptr<int> >::type, int);
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_ref_ptr<X> >::type, X);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_ref_ptr<int const> >::type, int const);
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_ref_ptr<X const> >::type, X const);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_value_ptr<int> >::type, int const);
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_value_ptr<X> >::type, X const);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_value_ptr<int const> >::type, int const);
|
||||
STATIC_ASSERT_SAME(boost::pointee<proxy_value_ptr<X const> >::type, X const);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<int*>::type, int);
|
||||
STATIC_ASSERT_SAME(boost::pointee<int const*>::type, int const);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<X*>::type, X);
|
||||
STATIC_ASSERT_SAME(boost::pointee<X const*>::type, X const);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::auto_ptr<int> >::type, int);
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::auto_ptr<X> >::type, X);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::auto_ptr<int const> >::type, int const);
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::auto_ptr<X const> >::type, X const);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::list<int>::iterator >::type, int);
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::list<X>::iterator >::type, X);
|
||||
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::list<int>::const_iterator >::type, int const);
|
||||
STATIC_ASSERT_SAME(boost::pointee<std::list<X>::const_iterator >::type, X const);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user