mirror of
https://github.com/boostorg/iterator.git
synced 2025-07-29 20:37:17 +02:00
Began tutorial and examples.
[SVN r21584]
This commit is contained in:
@ -31,7 +31,7 @@ Motivation
|
||||
Tutorial Example
|
||||
================
|
||||
|
||||
I'm working on a Tutorial example to go here.
|
||||
.. include:: iterator_facade_tutorial.rst
|
||||
|
||||
Reference
|
||||
=========
|
||||
|
73
doc/iterator_facade_tutorial.rst
Executable file
73
doc/iterator_facade_tutorial.rst
Executable file
@ -0,0 +1,73 @@
|
||||
.. 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)
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
In this section we'll walk through the implementation of a few
|
||||
iterators using ``iterator_facade``, based around the simple
|
||||
example of a linked list of polymorphic objects.
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
Say we've written a polymorphic linked list node as follows::
|
||||
|
||||
# include <iostream>
|
||||
|
||||
struct node_base
|
||||
{
|
||||
node_base() : m_next(0) {}
|
||||
|
||||
virtual ~node_base() { delete m_next; }
|
||||
|
||||
node_base* next() const { return m_next; }
|
||||
|
||||
// print to the stream
|
||||
virtual void print(std::ostream& s) const = 0;
|
||||
|
||||
// double the value
|
||||
virtual void twice() = 0;
|
||||
|
||||
void append(node_base* p)
|
||||
{
|
||||
if (m_next)
|
||||
m_next->append(p);
|
||||
else
|
||||
m_next = p;
|
||||
}
|
||||
|
||||
private:
|
||||
node_base* m_next;
|
||||
};
|
||||
|
||||
Lists can hold objects of different types by linking together
|
||||
specializations of the following template::
|
||||
|
||||
template <class T>
|
||||
struct node : node_base
|
||||
{
|
||||
node(T x)
|
||||
: m_value(x)
|
||||
{}
|
||||
|
||||
void print(std::ostream& s) const { s << this->m_value; }
|
||||
void twice() { m_value += m_value; }
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
};
|
||||
|
||||
And we can print any node using the following streaming operator::
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, node_base const& n)
|
||||
{
|
||||
n.print(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
.. sidebar:: Note
|
||||
|
||||
This is in progress; check the ../example directory for code.
|
@ -1 +1,9 @@
|
||||
unit-test ia1 : reverse_iterator.cpp : <sysinclude>../../.. <sysinclude>$(BOOST) ;
|
||||
subproject libs/iterator/example ;
|
||||
|
||||
import testing ;
|
||||
|
||||
test-suite iterator_examples
|
||||
: [ run reverse_iterator.cpp ]
|
||||
[ run node_iterator1.cpp ]
|
||||
[ run node_iterator2.cpp ]
|
||||
;
|
||||
|
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 twice() = 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 twice() { 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::twice)
|
||||
);
|
||||
|
||||
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)
|
||||
{}
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
private:
|
||||
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::twice)
|
||||
);
|
||||
|
||||
std::copy(
|
||||
node_const_iterator(nodes.get()), node_const_iterator()
|
||||
, std::ostream_iterator<node_base>(std::cout, "/")
|
||||
);
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
76
example/node_iterator2.hpp
Executable file
76
example/node_iterator2.hpp
Executable file
@ -0,0 +1,76 @@
|
||||
// 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_facade.hpp>
|
||||
|
||||
# ifndef BOOST_NO_SFINAE
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/utility/enable_if.hpp>
|
||||
# endif
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <class Value>
|
||||
class node_iterator
|
||||
: public boost::iterator_facade<
|
||||
node_iterator<Value>
|
||||
, Value
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
private:
|
||||
enum enabler {};
|
||||
|
||||
public:
|
||||
node_iterator()
|
||||
: m_node(0)
|
||||
{}
|
||||
|
||||
explicit node_iterator(Value* p)
|
||||
: m_node(p)
|
||||
{}
|
||||
|
||||
template <class OtherValue>
|
||||
node_iterator(
|
||||
node_iterator<OtherValue> const& other
|
||||
# ifndef BOOST_NO_SFINAE
|
||||
, typename boost::enable_if<boost::is_convertible<OtherValue*,Value*>,enabler*>::type = 0
|
||||
# endif
|
||||
)
|
||||
: m_node(other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
# if !BOOST_WORKAROUND(__GNUC__, == 2)
|
||||
private: // GCC2 can't even grant that friendship to template member functions
|
||||
# endif
|
||||
template <class OtherValue>
|
||||
bool equal(node_iterator<OtherValue> const& other) const
|
||||
{ return this->m_node == other.m_node; }
|
||||
|
||||
public:
|
||||
void increment()
|
||||
{ m_node = m_node->next(); }
|
||||
|
||||
Value& dereference() const
|
||||
{ return *m_node; }
|
||||
|
||||
# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
public:
|
||||
# else
|
||||
template <class> friend class node_iterator;
|
||||
# endif
|
||||
Value* m_node;
|
||||
};
|
||||
}
|
||||
|
||||
typedef impl::node_iterator<node_base> node_iterator;
|
||||
typedef impl::node_iterator<node_base const> node_const_iterator;
|
||||
|
||||
#endif // NODE_ITERATOR2_DWA2004110_HPP
|
@ -1,4 +1,4 @@
|
||||
#include <boost/iterator/iterator_adaptors.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/cstdlib.hpp>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
@ -7,9 +7,7 @@
|
||||
int main()
|
||||
{
|
||||
int x[] = { 1, 2, 3, 4 };
|
||||
boost::reverse_iterator<int*, int, int&, int*,
|
||||
boost::iterator_tag<boost::mutable_lvalue_iterator_tag, boost::random_access_traversal_tag>
|
||||
, std::ptrdiff_t> first(x + 4), last(x);
|
||||
boost::reverse_iterator<int*> first(x + 4), last(x);
|
||||
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user