diff --git a/doc/iterator_facade.rst b/doc/iterator_facade.rst index 8326a63..a48ede2 100644 --- a/doc/iterator_facade.rst +++ b/doc/iterator_facade.rst @@ -31,7 +31,7 @@ Motivation Tutorial Example ================ -I'm working on a Tutorial example to go here. +.. include:: iterator_facade_tutorial.rst Reference ========= diff --git a/doc/iterator_facade_tutorial.rst b/doc/iterator_facade_tutorial.rst new file mode 100755 index 0000000..3437bef --- /dev/null +++ b/doc/iterator_facade_tutorial.rst @@ -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 + + 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 + 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. \ No newline at end of file diff --git a/example/Jamfile b/example/Jamfile index 921ff30..fce5509 100644 --- a/example/Jamfile +++ b/example/Jamfile @@ -1 +1,9 @@ -unit-test ia1 : reverse_iterator.cpp : ../../.. $(BOOST) ; \ No newline at end of file +subproject libs/iterator/example ; + +import testing ; + +test-suite iterator_examples + : [ run reverse_iterator.cpp ] + [ run node_iterator1.cpp ] + [ run node_iterator2.cpp ] + ; diff --git a/example/node.hpp b/example/node.hpp new file mode 100755 index 0000000..b9e482c --- /dev/null +++ b/example/node.hpp @@ -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 + +// 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 +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 diff --git a/example/node_iterator1.cpp b/example/node_iterator1.cpp new file mode 100755 index 0000000..2b3ac00 --- /dev/null +++ b/example/node_iterator1.cpp @@ -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 +#include +#include +#include +#include + +int main() +{ + std::auto_ptr > nodes(new node(42)); + nodes->append(new node(" is greater than ")); + nodes->append(new node(13)); + + std::copy( + node_iterator(nodes.get()), node_iterator() + , std::ostream_iterator(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(std::cout, "/") + ); + std::cout << std::endl; +} diff --git a/example/node_iterator1.hpp b/example/node_iterator1.hpp new file mode 100755 index 0000000..281f30a --- /dev/null +++ b/example/node_iterator1.hpp @@ -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 + +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 diff --git a/example/node_iterator2.cpp b/example/node_iterator2.cpp new file mode 100755 index 0000000..9985c6f --- /dev/null +++ b/example/node_iterator2.cpp @@ -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 +#include +#include +#include +#include +#include + +int main() +{ + std::auto_ptr > nodes(new node(42)); + nodes->append(new node(" is greater than ")); + nodes->append(new node(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(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(std::cout, "/") + ); + std::cout << std::endl; + return 0; +} diff --git a/example/node_iterator2.hpp b/example/node_iterator2.hpp new file mode 100755 index 0000000..194cf95 --- /dev/null +++ b/example/node_iterator2.hpp @@ -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 + +# ifndef BOOST_NO_SFINAE +# include +# include +# endif + +namespace impl +{ + template + class node_iterator + : public boost::iterator_facade< + node_iterator + , Value + , boost::forward_traversal_tag + > + { + private: + enum enabler {}; + + public: + node_iterator() + : m_node(0) + {} + + explicit node_iterator(Value* p) + : m_node(p) + {} + + template + node_iterator( + node_iterator const& other +# ifndef BOOST_NO_SFINAE + , typename boost::enable_if,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 + bool equal(node_iterator 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 friend class node_iterator; +# endif + Value* m_node; + }; +} + +typedef impl::node_iterator node_iterator; +typedef impl::node_iterator node_const_iterator; + +#endif // NODE_ITERATOR2_DWA2004110_HPP diff --git a/example/reverse_iterator.cpp b/example/reverse_iterator.cpp index ffe6e3d..522cb9f 100644 --- a/example/reverse_iterator.cpp +++ b/example/reverse_iterator.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -7,9 +7,7 @@ int main() { int x[] = { 1, 2, 3, 4 }; - boost::reverse_iterator - , std::ptrdiff_t> first(x + 4), last(x); + boost::reverse_iterator first(x + 4), last(x); std::copy(first, last, std::ostream_iterator(std::cout, " ")); std::cout << std::endl; return 0;