Began tutorial and examples.

[SVN r21584]
This commit is contained in:
Dave Abrahams
2004-01-11 01:02:36 +00:00
parent 6c62f31f0a
commit 59340bca4c
9 changed files with 340 additions and 6 deletions

View File

@ -31,7 +31,7 @@ Motivation
Tutorial Example
================
I'm working on a Tutorial example to go here.
.. include:: iterator_facade_tutorial.rst
Reference
=========

View 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.

View File

@ -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
View 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
View 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
View 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
View 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
View 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

View File

@ -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;