diff --git a/doc/facade_iterator_category.rst b/doc/facade_iterator_category.rst new file mode 100755 index 0000000..6b60d85 --- /dev/null +++ b/doc/facade_iterator_category.rst @@ -0,0 +1,53 @@ +.. |iterator-category| replace:: *iterator-category* +.. _iterator-category: + +.. parsed-literal:: + + *iterator-category*\ (C,R,V) := + if (C is convertible to std::input_iterator_tag + || C is convertible to std::output_iterator_tag + ) + return C + + else if (C is not convertible to incrementable_traversal_tag) + *the program is ill-formed* + + else return a type X satisfying the following two constraints: + + 1. X is convertible to X1, and not to any more-derived + type, where X1 is defined by: + + if (R is a reference type + && C is convertible to forward_traversal_tag) + { + if (C is convertible to random_access_traversal_tag) + X1 = random_access_iterator_tag + else if (C is convertible to bidirectional_traversal_tag) + X1 = bidirectional_iterator_tag + else + X1 = forward_iterator_tag + } + else + { + if (C is convertible to single_pass_traversal_tag + && R is convertible to V) + X1 = input_iterator_tag + else + X1 = C + } + + 2. |category-to-traversal|_\ (X) is convertible to the most + derived traversal tag type to which X is also + convertible, and not to any more-derived traversal tag + type. + +.. |category-to-traversal| replace:: *category-to-traversal* +.. _`category-to-traversal`: new-iter-concepts.html#category-to-traversal + +[Note: the intention is to allow ``iterator_category`` to be one of +the five original category tags when convertibility to one of the +traversal tags would add no information] + +.. 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) diff --git a/doc/indirect_reference_ref.rst b/doc/indirect_reference_ref.rst new file mode 100755 index 0000000..f222d7e --- /dev/null +++ b/doc/indirect_reference_ref.rst @@ -0,0 +1,29 @@ +.. 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) + +:: + + template + struct indirect_reference + { + typedef /* see below */ type; + }; + +:Requires: For an object ``x`` of type ``Dereferenceable``, ``*x`` + is well-formed. If ``++x`` is ill-formed it shall neither be + ambiguous nor shall it violate access control, and + ``pointee::type&`` shall be well-formed. + Otherwise ``iterator_traits::reference`` shall + be well formed. [Note: These requirements need not apply to + explicit or partial specializations of ``indirect_reference``] + +``type`` is determined according to the following algorithm, where +``x`` is an object of type ``Dereferenceable``:: + + if ( ++x is ill-formed ) + return ``pointee::type&`` + else + std::iterator_traits::reference + + \ No newline at end of file diff --git a/doc/iterator_adaptor_tutorial.rst b/doc/iterator_adaptor_tutorial.rst new file mode 100755 index 0000000..ed1aa7e --- /dev/null +++ b/doc/iterator_adaptor_tutorial.rst @@ -0,0 +1,131 @@ +.. 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) + +In this section we'll further refine the ``node_iter`` class +template we developed in the |fac_tut|_. If you haven't already +read that material, you should go back now and check it out because +we're going to pick up right where it left off. + +.. |fac_tut| replace:: ``iterator_facade`` tutorial +.. _fac_tut: iterator_facade.html#tutorial-example + +.. sidebar:: ``node_base*`` really *is* an iterator + + It's not really a very interesting iterator, since ``node_base`` + is an abstract class: a pointer to a ``node_base`` just points + at some base subobject of an instance of some other class, and + incrementing a ``node_base*`` moves it past this base subobject + to who-knows-where? The most we can do with that incremented + position is to compare another ``node_base*`` to it. In other + words, the original iterator traverses a one-element array. + +You probably didn't think of it this way, but the ``node_base*`` +object which underlies ``node_iterator`` is itself an iterator, +just like all other pointers. If we examine that pointer closely +from an iterator perspective, we can see that it has much in common +with the ``node_iterator`` we're building. First, they share most +of the same associated types (``value_type``, ``reference``, +``pointer``, and ``difference_type``). Second, even some of the +core functionality is the same: ``operator*`` and ``operator==`` on +the ``node_iterator`` return the result of invoking the same +operations on the underlying pointer, via the ``node_iterator``\ 's +|dereference_and_equal|_). However, the ``operator++`` for +``node_iterator`` behaves differently than for ``node_base*`` +since it follows the ``m_next`` pointer. + +.. |dereference_and_equal| replace:: ``dereference`` and ``equal`` member functions +.. _dereference_and_equal: iterator_facade.html#implementing-the-core-operations + +It turns out that the pattern of building an iterator on another +iterator-like type (the ``Base`` [#base]_ type) while modifying +just a few aspects of the underlying type's behavior is an +extremely common one, and it's the pattern addressed by +``iterator_adaptor``. Using ``iterator_adaptor`` is very much like +using ``iterator_facade``, but because iterator_adaptor tries to +mimic as much of the ``Base`` type's behavior as possible, we +neither have to supply a ``Value`` argument, nor implement any core +behaviors other than ``increment``. The implementation of +``node_iter`` is thus reduced to:: + + template + class node_iter + : public boost::iterator_adaptor< + node_iter // 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*, boost::use_default, boost::forward_traversal_tag + > super_t; + + public: + node_iter() + : super_t(0) {} + + explicit node_iter(Value* p) + : super_t(p) {} + + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() + ) + : super_t(other.base()) {} + + private: + friend class boost::iterator_core_access; + void increment() { this->base_reference() = this->base()->next(); } + }; + +You can see an example program which exercises this version of the +node iterators `here`__. + +__ ../example/node_iterator3.cpp + +In the case of ``node_iter``, it's not very compelling to pass +``boost::use_default`` as ``iterator_adaptor``\ 's ``Value`` +argument; we could have just passed ``node_iter``\ 's ``Value`` +along to ``iterator_adaptor``, and that'd even be shorter! Most +iterator class templates built with ``iterator_adaptor`` are +parameterized on another iterator type, rather than on its +``value_type``. For example, ``boost::reverse_iterator`` takes an +iterator type argument and reverses its direction of traversal, +since the original iterator and the reversed one have all the same +associated types, ``iterator_adaptor``\ 's delegation of default +types to its ``Base`` saves the implementor of +``boost::reverse_iterator`` from writing + +.. parsed-literal:: + + std::iterator_traits::*some-associated-type* + +at least four times. + +We urge you to review the documentation and implementations of +|reverse_iterator|_ and the other Boost `specialized iterator +adaptors`__ to get an idea of the sorts of things you can do with +``iterator_adaptor``. In particular, have a look at +|transform_iterator|_, which is perhaps the most straightforward +adaptor, and also |counting_iterator|_, which demonstrates that +``iterator_adaptor``\ 's ``Base`` type needn't be an iterator. + +.. |reverse_iterator| replace:: ``reverse_iterator`` +.. _reverse_iterator: reverse_iterator.html + +.. |counting_iterator| replace:: ``counting_iterator`` +.. _counting_iterator: counting_iterator.html + +.. |transform_iterator| replace:: ``transform_iterator`` +.. _transform_iterator: transform_iterator.html + +__ index.html#specialized-adaptors + diff --git a/doc/iterator_facade_tutorial.rst b/doc/iterator_facade_tutorial.rst new file mode 100755 index 0000000..10980ed --- /dev/null +++ b/doc/iterator_facade_tutorial.rst @@ -0,0 +1,519 @@ +.. 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) + +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. This example was +inspired by a `posting`__ by Keith Macdonald on the `Boost-Users`_ +mailing list. + +.. _`Boost-Users`: ../../../more/mailing_lists.htm#users + +__ http://thread.gmane.org/gmane.comp.lib.boost.user/5100 + +The Problem +----------- + +Say we've written a polymorphic linked list node base class:: + + # include + + struct node_base + { + node_base() : m_next(0) {} + + // Each node manages all of its tail nodes + virtual ~node_base() { delete m_next; } + + // Access the rest of the list + node_base* next() const { return m_next; } + + // print to the stream + virtual void print(std::ostream& s) const = 0; + + // double the value + 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; + }; + +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 double_me() { 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; + } + +Our first challenge is to build an appropriate iterator over these +lists. + +A Basic Iterator Using ``iterator_facade`` +------------------------------------------ + +We will construct a ``node_iterator`` class using inheritance from +``iterator_facade`` to implement most of the iterator's operations. + +:: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade<...> + { + ... + }; + + + +Template Arguments for ``iterator_facade`` +.......................................... + +``iterator_facade`` has several template parameters, so we must decide +what types to use for the arguments. The parameters are ``Derived``, +``Value``, ``CategoryOrTraversal``, ``Reference``, and ``Difference``. + + +``Derived`` +''''''''''' + +Because ``iterator_facade`` is meant to be used with the CRTP +[Cop95]_ the first parameter is the iterator class name itself, +``node_iterator``. + +``Value`` +''''''''' + +The ``Value`` parameter determines the ``node_iterator``\ 's +``value_type``. In this case, we are iterating over ``node_base`` +objects, so ``Value`` will be ``node_base``. + + +``CategoryOrTraversal`` +''''''''''''''''''''''' + +Now we have to determine which `iterator traversal concept`_ our +``node_iterator`` is going to model. Singly-linked lists only have +forward links, so our iterator can't can't be a `bidirectional +traversal iterator`_. Our iterator should be able to make multiple +passes over the same linked list (unlike, say, an +``istream_iterator`` which consumes the stream it traverses), so it +must be a `forward traversal iterator`_. Therefore, we'll pass +``boost::forward_traversal_tag`` in this position [#category]_. + +.. [#category] ``iterator_facade`` also supports old-style category + tags, so we could have passed ``std::forward_iterator_tag`` here; + either way, the resulting iterator's ``iterator_category`` will + end up being ``std::forward_iterator_tag``. + +``Reference`` +''''''''''''' + +The ``Reference`` argument becomes the type returned by +``node_iterator``\ 's dereference operation, and will also be the +same as ``std::iterator_traits::reference``. The +library's default for this parameter is ``Value&``; since +``node_base&`` is a good choice for the iterator's ``reference`` +type, we can omit this argument, or pass ``use_default``. + +``Difference`` +'''''''''''''' + +The ``Difference`` argument determines how the distance between +two ``node_iterator``\ s will be measured and will also be the +same as ``std::iterator_traits::difference_type``. +The library's default for ``Difference`` is ``std::ptrdiff_t``, an +appropriate type for measuring the distance between any two +addresses in memory, and one that works for almost any iterator, +so we can omit this argument, too. + +The declaration of ``node_iterator`` will therefore look something +like:: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + ... + }; + +Constructors and Data Members +............................. + +Next we need to decide how to represent the iterator's position. +This representation will take the form of data members, so we'll +also need to write constructors to initialize them. The +``node_iterator``\ 's position is quite naturally represented using +a pointer to a ``node_base``. We'll need a constructor to build an +iterator from a ``node_base*``, and a default constructor to +satisfy the `forward traversal iterator`_ requirements [#default]_. +Our ``node_iterator`` then becomes:: + + # 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) + {} + + private: + ... + node_base* m_node; + }; + +.. [#default] Technically, the C++ standard places almost no + requirements on a default-constructed iterator, so if we were + really concerned with efficiency, we could've written the + default constructor to leave ``m_node`` uninitialized. + +Implementing the Core Operations +................................ + +The last step is to implement the `core operations`_ required by +the concepts we want our iterator to model. Referring to the +table__, we can see that the first three rows are applicable +because ``node_iterator`` needs to satisfy the requirements for +`readable iterator`_, `single pass iterator`_, and `incrementable +iterator`_. + +__ `core operations`_ + +We therefore need to supply ``dereference``, +``equal``, and ``increment`` members. We don't want these members +to become part of ``node_iterator``\ 's public interface, so we can +make them private and grant friendship to +``boost::iterator_core_access``, a "back-door" that +``iterator_facade`` uses to get access to the core operations:: + + # 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) {} + + 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; + }; + +Voilą; a complete and conforming readable, forward-traversal +iterator! For a working example of its use, see `this program`__. + +__ ../example/node_iterator1.cpp + +A constant ``node_iterator`` +---------------------------- + +.. Sidebar:: Constant and Mutable iterators + + The term **mutable iterator** means an iterator through which + the object it references (its "referent") can be modified. A + **constant iterator** is one which doesn't allow modification of + its referent. + + The words *constant* and *mutable* don't refer to the ability to + modify the iterator itself. For example, an ``int const*`` is a + non-\ ``const`` *constant iterator*, which can be incremented + but doesn't allow modification of its referent, and ``int* + const`` is a ``const`` *mutable iterator*, which cannot be + modified but which allows modification of its referent. + + Confusing? We agree, but those are the standard terms. It + probably doesn't help much that a container's constant iterator + is called ``const_iterator``. + +Now, our ``node_iterator`` gives clients access to both ``node``\ +'s ``print(std::ostream&) const`` member function, but also its +mutating ``double_me()`` member. If we wanted to build a +*constant* ``node_iterator``, we'd only have to make three +changes: + +.. parsed-literal:: + + class const_node_iterator + : public boost::iterator_facade< + node_iterator + , node_base **const** + , boost::forward_traversal_tag + > + { + public: + const_node_iterator() + : m_node(0) {} + + explicit const_node_iterator(node_base* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + void increment() { m_node = m_node->next(); } + + bool equal(const_node_iterator const& other) const + { + return this->m_node == other.m_node; + } + + node_base **const**\ & dereference() const { return \*m_node; } + + node_base **const**\ * m_node; + }; + +.. Sidebar:: ``const`` and an iterator's ``value_type`` + + The C++ standard requires an iterator's ``value_type`` *not* be + ``const``\ -qualified, so ``iterator_facade`` strips the + ``const`` from its ``Value`` parameter in order to produce the + iterator's ``value_type``. Making the ``Value`` argument + ``const`` provides a useful hint to ``iterator_facade`` that the + iterator is a *constant iterator*, and the default ``Reference`` + argument will be correct for all lvalue iterators. + +As a matter of fact, ``node_iterator`` and ``const_node_iterator`` +are so similar that it makes sense to factor the common code out +into a template as follows:: + + template + class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() + { m_node = m_node->next(); } + + Value& dereference() const + { return *m_node; } + + Value* m_node; + }; + typedef node_iter node_iterator; + typedef node_iter node_const_iterator; + + +Interoperability +---------------- + +Our ``const_node_iterator`` works perfectly well on its own, but +taken together with ``node_iterator`` it doesn't quite meet +expectations. For example, we'd like to be able to pass a +``node_iterator`` where a ``node_const_iterator`` was expected, +just as you can with ``std::list``\ 's ``iterator`` and +``const_iterator``. Furthermore, given a ``node_iterator`` and a +``node_const_iterator`` into the same list, we should be able to +compare them for equality. + +This expected ability to use two different iterator types together +is known as |interoperability|_. Achieving interoperability in +our case is as simple as templatizing the ``equal`` function and +adding a templatized converting constructor [#broken]_ [#random]_:: + + template + class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + template + node_iter(node_iter const& other) + : m_node(other.m_node) {} + + private: + friend class boost::iterator_core_access; + template friend class node_iter; + + template + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() + { m_node = m_node->next(); } + + Value& dereference() const + { return *m_node; } + + Value* m_node; + }; + typedef impl::node_iterator node_iterator; + typedef impl::node_iterator node_const_iterator; + +.. |interoperability| replace:: **interoperability** +.. _interoperability: new-iter-concepts.html#interoperable-iterators-lib-interoperable-iterators + +.. [#broken] If you're using an older compiler and it can't handle + this example, see the `example code`__ for workarounds. + +.. [#random] If ``node_iterator`` had been a `random access + traversal iterator`_, we'd have had to templatize its + ``distance_to`` function as well. + + +__ ../example/node_iterator2.hpp + +You can see an example program which exercises our interoperable +iterators `here`__. + +__ ../example/node_iterator2.cpp + +Telling the Truth +----------------- + +Now ``node_iterator`` and ``node_const_iterator`` behave exactly as +you'd expect... almost. We can compare them and we can convert in +one direction: from ``node_iterator`` to ``node_const_iterator``. +If we try to convert from ``node_const_iterator`` to +``node_iterator``, we'll get an error when the converting +constructor tries to initialize ``node_iterator``\ 's ``m_node``, a +``node*`` with a ``node const*``. So what's the problem? + +The problem is that +``boost::``\ |is_convertible|_\ ``::value`` +will be ``true``, but it should be ``false``. |is_convertible|_ +lies because it can only see as far as the *declaration* of +``node_iter``\ 's converting constructor, but can't look inside at +the *definition* to make sure it will compile. A perfect solution +would make ``node_iter``\ 's converting constructor disappear when +the ``m_node`` conversion would fail. + +.. |is_convertible| replace:: ``is_convertible`` +.. _is_convertible: ../../type_traits/index.html#relationships + +In fact, that sort of magic is possible using +|enable_if|__. By rewriting the converting constructor as +follows, we can remove it from the overload set when it's not +appropriate:: + + #include + #include + + ... + + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() + ) + : m_node(other.m_node) {} + +.. |enable_if| replace:: ``boost::enable_if`` +__ ../../utility/enable_if.html + + +Wrap Up +------- + +This concludes our ``iterator_facade`` tutorial, but before you +stop reading we urge you to take a look at |iterator_adaptor|__. +There's another way to approach writing these iterators which might +even be superior. + +.. |iterator_adaptor| replace:: ``iterator_adaptor`` +__ iterator_adaptor.html + +.. _`iterator traversal concept`: new-iter-concepts.html#iterator-traversal-concepts-lib-iterator-traversal +.. _`readable iterator`: new-iter-concepts.html#readable-iterators-lib-readable-iterators +.. _`lvalue iterator`: new-iter-concepts.html#lvalue-iterators-lib-lvalue-iterators +.. _`single pass iterator`: new-iter-concepts.html#single-pass-iterators-lib-single-pass-iterators +.. _`incrementable iterator`: new-iter-concepts.html#incrementable-iterators-lib-incrementable-iterators +.. _`forward traversal iterator`: new-iter-concepts.html#forward-traversal-iterators-lib-forward-traversal-iterators +.. _`bidirectional traversal iterator`: new-iter-concepts.html#bidirectional-traversal-iterators-lib-bidirectional-traversal-iterators +.. _`random access traversal iterator`: new-iter-concepts.html#random-access-traversal-iterators-lib-random-access-traversal-iterators + diff --git a/doc/make_filter_iterator.rst b/doc/make_filter_iterator.rst new file mode 100755 index 0000000..e4cd877 --- /dev/null +++ b/doc/make_filter_iterator.rst @@ -0,0 +1,16 @@ + +:: + + template + filter_iterator + make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + +:Returns: filter_iterator(f, x, end) + +:: + + template + filter_iterator + make_filter_iterator(Iterator x, Iterator end = Iterator()); + +:Returns: filter_iterator(x, end) diff --git a/doc/pointee.html b/doc/pointee.html new file mode 100755 index 0000000..4ca16d8 --- /dev/null +++ b/doc/pointee.html @@ -0,0 +1,179 @@ + + + + + + +pointee and indirect_reference + + + + + + + +
+

pointee and indirect_reference

+ +++ + + + + + + + + + + + +
Author:David Abrahams
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting
Date:2004-01-13
Copyright:Copyright David Abrahams 2004. All rights reserved
+ +++ + + + +
abstract:Provides the capability to deduce the referent types of +pointers, smart pointers and iterators in generic code.
+
+

Overview

+

Have you ever wanted to write a generic function that can operate +on any kind of dereferenceable object? If you have, you've +probably run into the problem of how to determine the type that the +object "points at":

+
+template <class Dereferenceable>
+void f(Dereferenceable p)
+{
+    what-goes-here? value = *p;
+    ...
+}
+
+
+

pointee

+

It turns out to be impossible to come up with a fully-general +algorithm to do determine what-goes-here directly, but it is +possible to require that pointee<Dereferenceable>::type is +correct. Naturally, pointee has the same difficulty: it can't +determine the appropriate ::type reliably for all +Dereferenceables, but it makes very good guesses (it works +for all pointers, standard and boost smart pointers, and +iterators), and when it guesses wrongly, it can be specialized as +neccessary:

+
+namespace boost
+{
+  template <class T>
+  struct pointee<third_party_lib::smart_pointer<T> >
+  {
+      typedef T type;
+  };
+}
+
+
+
+

indirect_reference

+

indirect_reference<T>::type is rather more specialized than +pointee, and is meant to be used to forward the result of +dereferencing an object of its argument type. Most dereferenceable +types just return a reference to their pointee, but some return +proxy references or return the pointee by value. When that +information is needed, call on indirect_reference.

+

Both of these templates are essential to the correct functioning of +indirect_iterator.

+
+
+
+

Reference

+
+

pointee

+ + + +
+template <class Dereferenceable>
+struct pointee
+{
+    typedef /* see below */ type;
+};
+
+ +++ + + + +
Requires:For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +Dereferenceable::element_type shall be an accessible type. +Otherwise iterator_traits<Dereferenceable>::value_type shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of pointee]
+

type is determined according to the following algorithm, where +x is an object of type Dereferenceable:

+
+if ( ++x is ill-formed )
+{
+    return ``Dereferenceable::element_type``
+}
+else if (``*x`` is a mutable reference to
+         std::iterator_traits<Dereferenceable>::value_type)
+{
+    return iterator_traits<Dereferenceable>::value_type
+}
+else
+{
+    return iterator_traits<Dereferenceable>::value_type const
+}
+
+
+
+

indirect_reference

+ + + +
+template <class Dereferenceable>
+struct indirect_reference
+{
+    typedef /* see below */ type;
+};
+
+ +++ + + + +
Requires:For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +pointee<Dereferenceable>::type& shall be well-formed. +Otherwise iterator_traits<Dereferenceable>::reference shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of indirect_reference]
+

type is determined according to the following algorithm, where +x is an object of type Dereferenceable:

+
+if ( ++x is ill-formed )
+    return ``pointee<Dereferenceable>::type&``
+else
+    std::iterator_traits<Dereferenceable>::reference
+
+
+
+
+ + + + diff --git a/doc/pointee.rst b/doc/pointee.rst new file mode 100755 index 0000000..21b90a4 --- /dev/null +++ b/doc/pointee.rst @@ -0,0 +1,84 @@ +++++++++++++++++++++++++++++++++++++++++ + ``pointee`` and ``indirect_reference`` +++++++++++++++++++++++++++++++++++++++++ + +:Author: David Abrahams +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_ +:date: $Date$ +:copyright: Copyright David Abrahams 2004. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com + +:abstract: Provides the capability to deduce the referent types of + pointers, smart pointers and iterators in generic code. + +Overview +======== + +Have you ever wanted to write a generic function that can operate +on any kind of dereferenceable object? If you have, you've +probably run into the problem of how to determine the type that the +object "points at": + +.. parsed-literal:: + + template + void f(Dereferenceable p) + { + *what-goes-here?* value = \*p; + ... + } + + +``pointee`` +----------- + +It turns out to be impossible to come up with a fully-general +algorithm to do determine *what-goes-here* directly, but it is +possible to require that ``pointee::type`` is +correct. Naturally, ``pointee`` has the same difficulty: it can't +determine the appropriate ``::type`` reliably for all +``Dereferenceable``\ s, but it makes very good guesses (it works +for all pointers, standard and boost smart pointers, and +iterators), and when it guesses wrongly, it can be specialized as +neccessary:: + + namespace boost + { + template + struct pointee > + { + typedef T type; + }; + } + +``indirect_reference`` +---------------------- + +``indirect_reference::type`` is rather more specialized than +``pointee``, and is meant to be used to forward the result of +dereferencing an object of its argument type. Most dereferenceable +types just return a reference to their pointee, but some return +proxy references or return the pointee by value. When that +information is needed, call on ``indirect_reference``. + +Both of these templates are essential to the correct functioning of +|indirect_iterator|_. + +.. |indirect_iterator| replace:: ``indirect_iterator`` +.. _indirect_iterator: indirect_iterator.html + +Reference +========= + +``pointee`` +----------- + +.. include:: pointee_ref.rst + +``indirect_reference`` +---------------------- + +.. include:: indirect_reference_ref.rst + diff --git a/doc/pointee_ref.rst b/doc/pointee_ref.rst new file mode 100755 index 0000000..19aed24 --- /dev/null +++ b/doc/pointee_ref.rst @@ -0,0 +1,38 @@ +.. 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) + +:: + + template + struct pointee + { + typedef /* see below */ type; + }; + +:Requires: For an object ``x`` of type ``Dereferenceable``, ``*x`` + is well-formed. If ``++x`` is ill-formed it shall neither be + ambiguous nor shall it violate access control, and + ``Dereferenceable::element_type`` shall be an accessible type. + Otherwise ``iterator_traits::value_type`` shall + be well formed. [Note: These requirements need not apply to + explicit or partial specializations of ``pointee``] + +``type`` is determined according to the following algorithm, where +``x`` is an object of type ``Dereferenceable``:: + + if ( ++x is ill-formed ) + { + return ``Dereferenceable::element_type`` + } + else if (``*x`` is a mutable reference to + std::iterator_traits::value_type) + { + return iterator_traits::value_type + } + else + { + return iterator_traits::value_type const + } + + \ No newline at end of file diff --git a/doc/rst2html b/doc/rst2html new file mode 100755 index 0000000..bd8dc8f --- /dev/null +++ b/doc/rst2html @@ -0,0 +1,7 @@ +#!/bin/sh +PYTHONPATH="c:/src/docutils/docutils;c:/src/docutils/docutils/extras" +export PYTHONPATH +python c:/src/docutils/docutils/tools/html.py -gs $1 `echo $1 | sed 's/\(.*\)\..*/\1.html/'` + + + diff --git a/doc/scanrst.py b/doc/scanrst.py new file mode 100644 index 0000000..484d879 --- /dev/null +++ b/doc/scanrst.py @@ -0,0 +1,29 @@ +# 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) + +# This script accepts a list of .rst files to be processed and +# generates Makefile dependencies for .html and .rst files to stdout. +import os,sys +import re + +include = re.compile(r' *\.\. +(include|image):: +(.*)', re.MULTILINE) + +def deps(path, found): + dir = os.path.split(path)[0] + for m in re.findall(include, open(path).read()): + + dependency = os.path.normpath(os.path.join(dir,m[1])) + if dependency not in found: + found[dependency] = 1 + + if m[0] == 'include': + deps(dependency, found) + + return found + +for file in sys.argv[1:]: + found = deps(file, {}) + if found: + base = os.path.splitext(os.path.basename(file))[0] + print '%s.tex %s.html: %s' % (base, base, ' '.join(found.keys()))