| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> |
| <title>The multi pass iterator</title> |
| <link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.75.0"> |
| <link rel="home" href="../../index.html" title="Spirit 2.4.1"> |
| <link rel="up" href="../support.html" title="Supporting libraries"> |
| <link rel="prev" href="../support.html" title="Supporting libraries"> |
| <link rel="next" href="../faq.html" title="Spirit FAQ"> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
| <table cellpadding="2" width="100%"><tr> |
| <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> |
| <td align="center"><a href="../../../../../../index.html">Home</a></td> |
| <td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> |
| <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> |
| <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> |
| <td align="center"><a href="../../../../../../more/index.htm">More</a></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="../support.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../support.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../faq.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="spirit.support.multi_pass"></a><a class="link" href="multi_pass.html" title="The multi pass iterator">The multi pass iterator</a> |
| </h3></div></div></div> |
| <p> |
| Backtracking in <span class="emphasis"><em>Spirit.Qi</em></span> requires the use of the following |
| types of iterator: forward, bidirectional, or random access. Because of backtracking, |
| input iterators cannot be used. Therefore, the standard library classes |
| <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istreambuf_iterator</span></code> and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span></code>, |
| that fall under the category of input iterators, cannot be used. Another |
| input iterator that is of interest is one that wraps a lexer, such as LEX. |
| </p> |
| <div class="note"><table border="0" summary="Note"> |
| <tr> |
| <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td> |
| <th align="left">Note</th> |
| </tr> |
| <tr><td align="left" valign="top"><p> |
| In general, <span class="emphasis"><em>Spirit.Qi</em></span> generates recursive descent |
| parser which require backtracking parsers by design. For this reason we |
| need to provide at least forward iterators to any of <span class="emphasis"><em>Spirit.Qi</em></span>'s |
| API functions. This is not an absolute requirement though. In the future, |
| we shall see more deterministic parsers that require no more than 1 character |
| (token) of lookahead. Such parsers allow us to use input iterators such |
| as the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span></code> as is. |
| </p></td></tr> |
| </table></div> |
| <p> |
| Backtracking can be implemented only if we are allowed to save an iterator |
| position, i.e. making a copy of the current iterator. Unfortunately, with |
| an input iterator, there is no way to do so, and thus input iterators will |
| not work with backtracking in <span class="emphasis"><em>Spirit.Qi</em></span>. One solution |
| to this problem is to simply load all the data to be parsed into a container, |
| such as a vector or deque, and then pass the begin and end of the container |
| to <span class="emphasis"><em>Spirit.Qi</em></span>. This method can be too memory intensive |
| for certain applications, which is why the <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| iterator was created. |
| </p> |
| <a name="spirit.support.multi_pass.using_the_multi_pass"></a><h5> |
| <a name="id1202365"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.using_the_multi_pass">Using the |
| multi_pass</a> |
| </h5> |
| <p> |
| The <code class="computeroutput"><span class="identifier">multi_pass</span></code> iterator will |
| convert any input iterator into a forward iterator suitable for use with |
| <span class="emphasis"><em>Spirit.Qi</em></span>. <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| will buffer data when needed and will discard the buffer when its contents |
| is not needed anymore. This happens either if only one copy of the iterator |
| exists or if no backtracking can occur. |
| </p> |
| <p> |
| A grammar must be designed with care if the <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| iterator is used. Any rule that may need to backtrack, such as one that contains |
| an alternative, will cause data to be buffered. The rules that are optimal |
| to use are repetition constructs (as kleene and plus). |
| </p> |
| <p> |
| Sequences of the form <code class="computeroutput"><span class="identifier">a</span> <span class="special">>></span> <span class="identifier">b</span></code> |
| will buffer data as well. This is different from the behavior of <a href="../../../../../../libs/spirit/classic/index.html" target="_top"><span class="emphasis"><em>Spirit.Classic</em></span></a> |
| but for a good reason. Sequences need to reset the current iterator to its |
| initial state if one of the components of a sequence fails to match. To compensate |
| for this behavior we added functionality to the <code class="computeroutput"><span class="identifier">expect</span></code> |
| parsers (i.e. constructs like <code class="computeroutput"><span class="identifier">a</span> |
| <span class="special">></span> <span class="identifier">b</span></code>). |
| Expectation points introduce deterministic points into the grammar ensuring |
| no backtracking can occur if they match. For this reason we clear the buffers |
| of any multi_pass iterator on each expectation point, ensuring minimal buffer |
| content even for large grammars. |
| </p> |
| <div class="important"><table border="0" summary="Important"> |
| <tr> |
| <td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../images/important.png"></td> |
| <th align="left">Important</th> |
| </tr> |
| <tr><td align="left" valign="top"> |
| <p> |
| If you use an error handler in conjunction with the <code class="computeroutput"><span class="identifier">expect</span></code> |
| parser while utilizing a <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| iterator and you intend to use the error handler to force a <code class="computeroutput"><span class="identifier">retry</span></code> or a <code class="computeroutput"><span class="identifier">fail</span></code> |
| (see the description of error handlers - <span class="bold"><strong>FIXME</strong></span>: |
| insert link), then you need to instantiate the error handler using <code class="computeroutput"><span class="identifier">retry</span></code> or <code class="computeroutput"><span class="identifier">fail</span></code>, |
| for instance: |
| </p> |
| <pre class="programlisting"><span class="identifier">rule</span> <span class="identifier">r</span><span class="special"><</span><span class="identifier">iterator_type</span><span class="special">></span> <span class="identifier">r</span><span class="special">;</span> |
| <span class="identifier">on_error</span><span class="special"><</span><span class="identifier">retry</span><span class="special">>(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">val</span><span class="special">(</span><span class="string">"Error!"</span><span class="special">));</span> |
| </pre> |
| <p> |
| If you fail to do so the resulting code will trigger an assert statement |
| at runtime. |
| </p> |
| </td></tr> |
| </table></div> |
| <p> |
| Any rule that repeats, such as kleene_star (<code class="computeroutput"><span class="special">*</span><span class="identifier">a</span></code>) or positive such as (<code class="computeroutput"><span class="special">+</span><span class="identifier">a</span></code>), will only buffer the data for the current |
| repetition. |
| </p> |
| <p> |
| In typical grammars, ambiguity and therefore lookahead is often localized. |
| In fact, many well designed languages are fully deterministic and require |
| no lookahead at all. Peeking at the first character from the input will immediately |
| determine the alternative branch to take. Yet, even with highly ambiguous |
| grammars, alternatives are often of the form <code class="computeroutput"><span class="special">*(</span><span class="identifier">a</span> <span class="special">|</span> <span class="identifier">b</span> |
| <span class="special">|</span> <span class="identifier">c</span> <span class="special">|</span> <span class="identifier">d</span><span class="special">)</span></code>. |
| The input iterator moves on and is never stuck at the beginning. Let's look |
| at a Pascal snippet for example: |
| </p> |
| <pre class="programlisting"><span class="identifier">program</span> <span class="special">=</span> |
| <span class="identifier">programHeading</span> <span class="special">>></span> <span class="identifier">block</span> <span class="special">>></span> <span class="char">'.'</span> |
| <span class="special">;</span> |
| |
| <span class="identifier">block</span> <span class="special">=</span> |
| <span class="special">*(</span> <span class="identifier">labelDeclarationPart</span> |
| <span class="special">|</span> <span class="identifier">constantDefinitionPart</span> |
| <span class="special">|</span> <span class="identifier">typeDefinitionPart</span> |
| <span class="special">|</span> <span class="identifier">variableDeclarationPart</span> |
| <span class="special">|</span> <span class="identifier">procedureAndFunctionDeclarationPart</span> |
| <span class="special">)</span> |
| <span class="special">>></span> <span class="identifier">statementPart</span> |
| <span class="special">;</span> |
| </pre> |
| <p> |
| Notice the alternatives inside the Kleene star in the rule block . The rule |
| gobbles the input in a linear manner and throws away the past history with |
| each iteration. As this is fully deterministic LL(1) grammar, each failed |
| alternative only has to peek 1 character (token). The alternative that consumes |
| more than 1 character (token) is definitely a winner. After which, the Kleene |
| star moves on to the next. |
| </p> |
| <p> |
| Now, after the lecture on the features to be careful with when using <code class="computeroutput"><span class="identifier">multi_pass</span></code>, you may think that <code class="computeroutput"><span class="identifier">multi_pass</span></code> is way too restrictive to use. |
| That's not the case. If your grammar is deterministic, you can make use of |
| the <code class="computeroutput"><span class="identifier">flush_multi_pass</span></code> pseudo |
| parser in your grammar to ensure that data is not buffered when unnecessary |
| (<code class="computeroutput"><span class="identifier">flush_multi_pass</span></code> is available |
| from the <span class="emphasis"><em>Spirit.Qi</em></span> parser <a href="../../../../repository/doc/html/index.html" target="_top">Repository</a>). |
| </p> |
| <p> |
| Here we present a minimal example showing a minimal use case. The <code class="computeroutput"><span class="identifier">multi_pass</span></code> iterator is highly configurable, |
| but the default policies have been chosen so that its easily usable with |
| input iterators such as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istreambuf_iterator</span></code>. |
| For the complete source code of this example please refer to <a href="../../../../example/support/multi_pass.cpp" target="_top">multi_pass.cpp</a>. |
| </p> |
| <p> |
| |
| </p> |
| <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">spirit</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">;</span> |
| <span class="keyword">using</span> <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space</span><span class="special">;</span> |
| <span class="keyword">using</span> <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">ascii</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span> |
| <span class="keyword">using</span> <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">qi</span><span class="special">::</span><span class="identifier">double_</span><span class="special">;</span> |
| <span class="keyword">using</span> <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">qi</span><span class="special">::</span><span class="identifier">eol</span><span class="special">;</span> |
| |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">ifstream</span> <span class="identifier">in</span><span class="special">(</span><span class="string">"multi_pass.txt"</span><span class="special">);</span> <span class="comment">// we get our input from this file |
| </span> <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">in</span><span class="special">.</span><span class="identifier">is_open</span><span class="special">())</span> <span class="special">{</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Could not open input file: 'multi_pass.txt'"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> |
| <span class="keyword">return</span> <span class="special">-</span><span class="number">1</span><span class="special">;</span> |
| <span class="special">}</span> |
| |
| <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">istreambuf_iterator</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="identifier">base_iterator_type</span><span class="special">;</span> |
| <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">multi_pass</span><span class="special"><</span><span class="identifier">base_iterator_type</span><span class="special">></span> <span class="identifier">first</span> <span class="special">=</span> |
| <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">make_default_multi_pass</span><span class="special">(</span><span class="identifier">base_iterator_type</span><span class="special">(</span><span class="identifier">in</span><span class="special">));</span> |
| |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">double</span><span class="special">></span> <span class="identifier">v</span><span class="special">;</span> |
| <span class="keyword">bool</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">qi</span><span class="special">::</span><span class="identifier">phrase_parse</span><span class="special">(</span><span class="identifier">first</span> |
| <span class="special">,</span> <span class="identifier">spirit</span><span class="special">::</span><span class="identifier">make_default_multi_pass</span><span class="special">(</span><span class="identifier">base_iterator_type</span><span class="special">())</span> |
| <span class="special">,</span> <span class="identifier">double_</span> <span class="special">>></span> <span class="special">*(</span><span class="char">','</span> <span class="special">>></span> <span class="identifier">double_</span><span class="special">)</span> <span class="comment">// recognize list of doubles |
| </span> <span class="special">,</span> <span class="identifier">space</span> <span class="special">|</span> <span class="char">'#'</span> <span class="special">>></span> <span class="special">*(</span><span class="identifier">char_</span> <span class="special">-</span> <span class="identifier">eol</span><span class="special">)</span> <span class="special">>></span> <span class="identifier">eol</span> <span class="comment">// comment skipper |
| </span> <span class="special">,</span> <span class="identifier">v</span><span class="special">);</span> <span class="comment">// data read from file |
| </span> |
| <span class="keyword">if</span> <span class="special">(!</span><span class="identifier">result</span><span class="special">)</span> <span class="special">{</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Failed parsing input file!"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> |
| <span class="keyword">return</span> <span class="special">-</span><span class="number">2</span><span class="special">;</span> |
| <span class="special">}</span> |
| |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Successfully parsed input file!"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <a name="spirit.support.multi_pass.using_the_flush_multi_pass_parser"></a><h5> |
| <a name="id1204725"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.using_the_flush_multi_pass_parser">Using |
| the flush_multi_pass parser</a> |
| </h5> |
| <p> |
| The <a href="http://boost-spirit.com" target="_top">Spirit</a> <a href="../../../../repository/doc/html/index.html" target="_top">Repository</a> |
| contains the <code class="computeroutput"><span class="identifier">flush_multi_pass</span></code> |
| parser component. This is usable in conjunction with the <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| iterator to minimize the buffering. It allows to insert explicit synchronization |
| points into your grammar where it is safe to clear any stored input as it |
| is ensured that no backtracking can occur at this point anymore. |
| </p> |
| <p> |
| When the <code class="computeroutput"><span class="identifier">flush_multi_pass</span></code> |
| parser is used with <code class="computeroutput"><span class="identifier">multi_pass</span></code>, |
| it will call <code class="computeroutput"><span class="identifier">multi_pass</span><span class="special">::</span><span class="identifier">clear_queue</span><span class="special">()</span></code>. |
| This will cause any buffered data to be erased. This also will invalidate |
| all other copies of multi_pass and they should not be used. If they are, |
| an <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">illegal_backtracking</span></code> exception will be |
| thrown. |
| </p> |
| <a name="spirit.support.multi_pass.the_multi_pass_policies"></a><h5> |
| <a name="id1204818"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.the_multi_pass_policies">The multi_pass |
| Policies</a> |
| </h5> |
| <p> |
| The <code class="computeroutput"><span class="identifier">multi_pass</span></code> iterator is |
| a templated class configurable using policies. The description of <code class="computeroutput"><span class="identifier">multi_pass</span></code> above is how it was originally |
| implemented (before it used policies), and is the default configuration now. |
| But, <code class="computeroutput"><span class="identifier">multi_pass</span></code> is capable |
| of much more. Because of the open-ended nature of policies, you can write |
| your own policy to make <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| behave in a way that we never before imagined. |
| </p> |
| <p> |
| The multi_pass class has two template parameters: |
| </p> |
| <div class="variablelist"> |
| <p class="title"><b>The multi_pass template parameters</b></p> |
| <dl> |
| <dt><span class="term">Input</span></dt> |
| <dd><p> |
| The type multi_pass uses to acquire it's input. This is typically an |
| input iterator, or functor. |
| </p></dd> |
| <dt><span class="term">Policies</span></dt> |
| <dd><p> |
| The combined policies to use to create an instance of a multi_pass |
| iterator. This combined policy type is described below |
| </p></dd> |
| </dl> |
| </div> |
| <p> |
| It is possible to implement all of the required functionality of the combined |
| policy in a single class. But it has shown to be more convenient to split |
| this into four different groups of functions, i.e. four separate, but well |
| coordinated policies. For this reason the <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| library implements a template <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">default_policy</span></code> |
| allowing to combine several different policies, each implementing one of |
| the functionality groups: |
| </p> |
| <div class="table"> |
| <a name="id1204926"></a><p class="title"><b>Table 12. Policies needed for default_policy template</b></p> |
| <div class="table-contents"><table class="table" summary="Policies needed for default_policy template"> |
| <colgroup> |
| <col> |
| <col> |
| </colgroup> |
| <thead><tr> |
| <th> |
| <p> |
| Template Parameter |
| </p> |
| </th> |
| <th> |
| <p> |
| Description |
| </p> |
| </th> |
| </tr></thead> |
| <tbody> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">OwnershipPolicy</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy determines how <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| deals with it's shared components. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">CheckingPolicy</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy determines how checking for invalid iterators is done. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">InputPolicy</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| A class that defines how <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| acquires its input. The <code class="computeroutput"><span class="identifier">InputPolicy</span></code> |
| is parameterized by the <code class="computeroutput"><span class="identifier">Input</span></code> |
| template parameter to the <code class="computeroutput"><span class="identifier">multi_pass</span></code>. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">StoragePolicy</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| The buffering scheme used by <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| is determined and managed by the StoragePolicy. |
| </p> |
| </td> |
| </tr> |
| </tbody> |
| </table></div> |
| </div> |
| <br class="table-break"><p> |
| The <code class="computeroutput"><span class="identifier">multi_pass</span></code> library contains |
| several predefined policy implementations for each of the policy types as |
| described above. First we will describe those predefined types. Afterwards |
| we will give some guidelines how you can write your own policy implementations. |
| </p> |
| <a name="spirit.support.multi_pass.predefined_policies"></a><h5> |
| <a name="id1205123"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.predefined_policies">Predefined |
| policies</a> |
| </h5> |
| <p> |
| All predefined <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| policies are defined in the namespace <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">iterator_policies</span></code>. |
| </p> |
| <div class="table"> |
| <a name="id1205165"></a><p class="title"><b>Table 13. Predefined policy classes</b></p> |
| <div class="table-contents"><table class="table" summary="Predefined policy classes"> |
| <colgroup> |
| <col> |
| <col> |
| </colgroup> |
| <thead><tr> |
| <th> |
| <p> |
| Class name |
| </p> |
| </th> |
| <th> |
| <p> |
| Description |
| </p> |
| </th> |
| </tr></thead> |
| <tbody> |
| <tr> |
| <td> |
| <p> |
| <span class="bold"><strong>InputPolicy</strong></span> classes |
| </p> |
| </td> |
| <td class="auto-generated"> </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">input_iterator</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy directs <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| to read from an input iterator of type <code class="computeroutput"><span class="identifier">Input</span></code>. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">buffering_input_iterator</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy directs <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| to read from an input iterator of type <code class="computeroutput"><span class="identifier">Input</span></code>. |
| Additionally it buffers the last character received from the underlying |
| iterator. This allows to wrap iterators not buffering the last |
| character on their own (as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istreambuf_iterator</span></code>). |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">istream</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy directs <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| to read from an input stream of type <code class="computeroutput"><span class="identifier">Input</span></code> |
| (usually a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span></code>). |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">lex_input</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy obtains it's input by calling yylex(), which would |
| typically be provided by a scanner generated by <a href="http://flex.sourceforge.net/" target="_top">Flex</a>. |
| If you use this policy your code must link against a <a href="http://flex.sourceforge.net/" target="_top">Flex</a> |
| generated scanner. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">functor_input</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This input policy obtains it's data by calling a functor of type |
| <code class="computeroutput"><span class="identifier">Input</span></code>. The functor |
| must meet certain requirements. It must have a typedef called |
| <code class="computeroutput"><span class="identifier">result_type</span></code> which |
| should be the type returned from <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code>. Also, since an input policy |
| needs a way to determine when the end of input has been reached, |
| the functor must contain a static variable named <code class="computeroutput"><span class="identifier">eof</span></code> which is comparable to a |
| variable of <code class="computeroutput"><span class="identifier">result_type</span></code>. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">split_functor_input</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This is essentially the same as the <code class="computeroutput"><span class="identifier">functor_input</span></code> |
| policy except that the (user supplied) function object exposes |
| separate <code class="computeroutput"><span class="identifier">unique</span></code> |
| and <code class="computeroutput"><span class="identifier">shared</span></code> sub |
| classes, allowing to integrate the functors <span class="emphasis"><em>unique</em></span> |
| data members with the <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| data items held by each instance and its <span class="emphasis"><em>shared</em></span> |
| data members will be integrated with the <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| members shared by all copies. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <span class="bold"><strong>OwnershipPolicy</strong></span> classes |
| </p> |
| </td> |
| <td class="auto-generated"> </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">ref_counted</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This class uses a reference counting scheme. The <code class="computeroutput"><span class="identifier">multi_pass</span></code> will delete it's shared |
| components when the count reaches zero. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">first_owner</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| When this policy is used, the first <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| created will be the one that deletes the shared data. Each copy |
| will not take ownership of the shared data. This works well for |
| <a href="http://boost-spirit.com" target="_top">Spirit</a>, since no dynamic |
| allocation of iterators is done. All copies are made on the stack, |
| so the original iterator has the longest lifespan. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <span class="bold"><strong>CheckingPolicy</strong></span> classes |
| </p> |
| </td> |
| <td class="auto-generated"> </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">no_check</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy does no checking at all. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">buf_id_check</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy keeps around a buffer id, or a buffer age. Every time |
| <code class="computeroutput"><span class="identifier">clear_queue</span><span class="special">()</span></code> |
| is called on a <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| iterator, it is possible that all other iterators become invalid. |
| When <code class="computeroutput"><span class="identifier">clear_queue</span><span class="special">()</span></code> is called, <code class="computeroutput"><span class="identifier">buf_id_check</span></code> |
| increments the buffer id. When an iterator is dereferenced, this |
| policy checks that the buffer id of the iterator matches the shared |
| buffer id. This policy is most effective when used together with |
| the <code class="computeroutput"><span class="identifier">split_std_deque</span></code> |
| StoragePolicy. It should not be used with the <code class="computeroutput"><span class="identifier">fixed_size_queue</span></code> |
| StoragePolicy, because it will not detect iterator dereferences |
| that are out of range. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| full_check |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy has not been implemented yet. When it is, it will keep |
| track of all iterators and make sure that they are all valid. This |
| will be mostly useful for debugging purposes as it will incur significant |
| overhead. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <span class="bold"><strong>StoragePolicy</strong></span> classes |
| </p> |
| </td> |
| <td class="auto-generated"> </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">split_std_deque</span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| Despite its name this policy keeps all buffered data in a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span></code>. All data is stored as |
| long as there is more than one iterator. Once the iterator count |
| goes down to one, and the queue is no longer needed, it is cleared, |
| freeing up memory. The queue can also be forcibly cleared by calling |
| <code class="computeroutput"><span class="identifier">multi_pass</span><span class="special">::</span><span class="identifier">clear_queue</span><span class="special">()</span></code>. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td> |
| <p> |
| <code class="computeroutput"><span class="identifier">fixed_size_queue</span><span class="special"><</span><span class="identifier">N</span><span class="special">></span></code> |
| </p> |
| </td> |
| <td> |
| <p> |
| This policy keeps a circular buffer that is size <code class="computeroutput"><span class="identifier">N</span><span class="special">+</span><span class="number">1</span></code> and stores <code class="computeroutput"><span class="identifier">N</span></code> |
| elements. <code class="computeroutput"><span class="identifier">fixed_size_queue</span></code> |
| is a template with a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span></code> |
| parameter that specified the queue size. It is your responsibility |
| to ensure that <code class="computeroutput"><span class="identifier">N</span></code> |
| is big enough for your parser. Whenever the foremost iterator is |
| incremented, the last character of the buffer is automatically |
| erased. Currently there is no way to tell if an iterator is trailing |
| too far behind and has become invalid. No dynamic allocation is |
| done by this policy during normal iterator operation, only on initial |
| construction. The memory usage of this <code class="computeroutput"><span class="identifier">StoragePolicy</span></code> |
| is set at <code class="computeroutput"><span class="identifier">N</span><span class="special">+</span><span class="number">1</span></code> bytes, unlike <code class="computeroutput"><span class="identifier">split_std_deque</span></code>, |
| which is unbounded. |
| </p> |
| </td> |
| </tr> |
| </tbody> |
| </table></div> |
| </div> |
| <br class="table-break"><a name="spirit.support.multi_pass.combinations__how_to_specify_your_own_custom_multi_pass"></a><h5> |
| <a name="id1205956"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.combinations__how_to_specify_your_own_custom_multi_pass">Combinations: |
| How to specify your own custom multi_pass</a> |
| </h5> |
| <p> |
| The beauty of policy based designs is that you can mix and match policies |
| to create your own custom iterator by selecting the policies you want. Here's |
| an example of how to specify a custom <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| that wraps an <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span></code>, |
| and is slightly more efficient than the default <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| (as generated by the <code class="computeroutput"><span class="identifier">make_default_multi_pass</span><span class="special">()</span></code> API function) because it uses the <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">first_owner</span></code> OwnershipPolicy and the <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">no_check</span></code> CheckingPolicy: |
| </p> |
| <pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">multi_pass</span><span class="special"><</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">default_policy</span><span class="special"><</span> |
| <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">first_owner</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">no_check</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">buffering_input_iterator</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">split_std_deque</span> |
| <span class="special">></span> |
| <span class="special">></span> <span class="identifier">first_owner_multi_pass_type</span><span class="special">;</span> |
| </pre> |
| <p> |
| The default template parameters for <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">default_policy</span></code> |
| are: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">ref_counted</span></code> OwnershipPolicy |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">no_check</span></code> CheckingPolicy, if <code class="computeroutput"><span class="identifier">BOOST_SPIRIT_DEBUG</span></code> is defined: <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">buf_id_check</span></code> CheckingPolicy |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">buffering_input_iterator</span></code> InputPolicy, |
| and |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">split_std_deque</span></code> StoragePolicy. |
| </li> |
| </ul></div> |
| <p> |
| So if you use <code class="computeroutput"><span class="identifier">multi_pass</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> |
| <span class="special">></span></code> you will get those pre-defined |
| behaviors while wrapping an <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span></code>. |
| </p> |
| <a name="spirit.support.multi_pass.dealing_with_constant_look_ahead"></a><h5> |
| <a name="id1206410"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.dealing_with_constant_look_ahead">Dealing |
| with constant look ahead</a> |
| </h5> |
| <p> |
| There is one other pre-defined class called <code class="computeroutput"><span class="identifier">look_ahead</span></code>. |
| The class <code class="computeroutput"><span class="identifier">look_ahead</span></code> is another |
| predefine <code class="computeroutput"><span class="identifier">multi_pass</span></code> iterator |
| type. It has two template parameters: <code class="computeroutput"><span class="identifier">Input</span></code>, |
| the type of the input iterator to wrap, and a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">N</span></code>, which specifies the size of the buffer |
| to the <code class="computeroutput"><span class="identifier">fixed_size_queue</span></code> policy. |
| While the default multi_pass configuration is designed for safety, <code class="computeroutput"><span class="identifier">look_ahead</span></code> is designed for speed. <code class="computeroutput"><span class="identifier">look_ahead</span></code> is derived from a multi_pass |
| with the following policies: <code class="computeroutput"><span class="identifier">input_iterator</span></code> |
| InputPolicy, <code class="computeroutput"><span class="identifier">first_owner</span></code> |
| OwnershipPolicy, <code class="computeroutput"><span class="identifier">no_check</span></code> |
| CheckingPolicy, and <code class="computeroutput"><span class="identifier">fixed_size_queue</span><span class="special"><</span><span class="identifier">N</span><span class="special">></span></code> |
| StoragePolicy. |
| </p> |
| <p> |
| This iterator is defined by including the files: |
| </p> |
| <pre class="programlisting"><span class="comment">// forwards to <boost/spirit/home/support/look_ahead.hpp> |
| </span><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">include</span><span class="special">/</span><span class="identifier">support_look_ahead</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| Also, see <a class="link" href="../structure/include.html" title="Include">Include Structure</a>. |
| </p> |
| <a name="spirit.support.multi_pass.reading_from_standard_input_streams"></a><h5> |
| <a name="id1206609"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.reading_from_standard_input_streams">Reading |
| from standard input streams</a> |
| </h5> |
| <p> |
| Yet another predefined iterator for wrapping standard input streams (usually |
| a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special"><></span></code>) |
| is called <code class="computeroutput"><span class="identifier">basic_istream_iterator</span><span class="special"><</span><span class="identifier">Char</span><span class="special">,</span> <span class="identifier">Traits</span><span class="special">></span></code>. This class is usable as a drop in replacement |
| for <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special"><</span><span class="identifier">Char</span><span class="special">,</span> <span class="identifier">Traits</span><span class="special">></span></code>. |
| Its only difference is that it is a forward iterator (instead of the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span></code>, |
| which is an input iterator). <code class="computeroutput"><span class="identifier">basic_istream_iterator</span></code> |
| is derived from a multi_pass with the following policies: <code class="computeroutput"><span class="identifier">istream</span></code> |
| InputPolicy, <code class="computeroutput"><span class="identifier">ref_counted</span></code> |
| OwnershipPolicy, <code class="computeroutput"><span class="identifier">no_check</span></code> |
| CheckingPolicy, and <code class="computeroutput"><span class="identifier">split_std_deque</span></code> |
| StoragePolicy. |
| </p> |
| <p> |
| There exists an additional predefined typedef: |
| </p> |
| <pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">basic_istream_iterator</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="special">></span> <span class="identifier">istream_iterator</span><span class="special">;</span> |
| </pre> |
| <p> |
| This iterator is defined by including the files: |
| </p> |
| <pre class="programlisting"><span class="comment">// forwards to <boost/spirit/home/support/istream_iterator.hpp> |
| </span><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">include</span><span class="special">/</span><span class="identifier">support_istream_iterator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| Also, see <a class="link" href="../structure/include.html" title="Include">Include Structure</a>. |
| </p> |
| <a name="spirit.support.multi_pass.how_to_write_a_functor_for_use_with_the__code__phrase_role__identifier__functor_input__phrase___code__inputpolicy"></a><h5> |
| <a name="id1206887"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.how_to_write_a_functor_for_use_with_the__code__phrase_role__identifier__functor_input__phrase___code__inputpolicy">How |
| to write a functor for use with the <code class="computeroutput"><span class="identifier">functor_input</span></code> |
| InputPolicy</a> |
| </h5> |
| <p> |
| If you want to use the <code class="computeroutput"><span class="identifier">functor_input</span></code> |
| InputPolicy, you can write your own function object that will supply the |
| input to <code class="computeroutput"><span class="identifier">multi_pass</span></code>. The |
| function object must satisfy several requirements. It must have a typedef |
| <code class="computeroutput"><span class="identifier">result_type</span></code> which specifies |
| the return type of its <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code>. This is standard practice in the STL. |
| Also, it must supply a static variable called eof which is compared against |
| to know whether the input has reached the end. Last but not least the function |
| object must be default constructible. Here is an example: |
| </p> |
| <pre class="programlisting"><span class="comment">// define the function object |
| </span><span class="keyword">class</span> <span class="identifier">iterate_a2m</span> |
| <span class="special">{</span> |
| <span class="keyword">public</span><span class="special">:</span> |
| <span class="keyword">typedef</span> <span class="keyword">char</span> <span class="identifier">result_type</span><span class="special">;</span> |
| |
| <span class="identifier">iterate_a2m</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">c</span><span class="special">(</span><span class="char">'A'</span><span class="special">)</span> <span class="special">{}</span> |
| <span class="identifier">iterate_a2m</span><span class="special">(</span><span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">c_</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span> <span class="special">{}</span> |
| |
| <span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()()</span> <span class="keyword">const</span> |
| <span class="special">{</span> |
| <span class="keyword">if</span> <span class="special">(</span><span class="identifier">c_</span> <span class="special">==</span> <span class="char">'M'</span><span class="special">)</span> |
| <span class="keyword">return</span> <span class="identifier">eof</span><span class="special">;</span> |
| <span class="keyword">return</span> <span class="identifier">c_</span><span class="special">++;</span> |
| <span class="special">}</span> |
| |
| <span class="keyword">static</span> <span class="identifier">result_type</span> <span class="identifier">eof</span><span class="special">;</span> |
| |
| <span class="keyword">private</span><span class="special">:</span> |
| <span class="keyword">char</span> <span class="identifier">c_</span><span class="special">;</span> |
| <span class="special">};</span> |
| |
| <span class="identifier">iterate_a2m</span><span class="special">::</span><span class="identifier">result_type</span> <span class="identifier">iterate_a2m</span><span class="special">::</span><span class="identifier">eof</span> <span class="special">=</span> <span class="identifier">iterate_a2m</span><span class="special">::</span><span class="identifier">result_type</span><span class="special">(</span><span class="char">'\0'</span><span class="special">);</span> |
| |
| <span class="comment">// create two iterators using the define function object, one of which is |
| </span><span class="comment">// an end iterator |
| </span><span class="keyword">typedef</span> <span class="identifier">multi_pass</span><span class="special"><</span><span class="identifier">iterate_a2m</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">functor_input</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">first_owner</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">no_check</span> |
| <span class="special">,</span> <span class="identifier">iterator_policies</span><span class="special">::</span><span class="identifier">split_std_deque</span><span class="special">></span> |
| <span class="identifier">functor_multi_pass_type</span><span class="special">;</span> |
| |
| <span class="identifier">functor_multi_pass_type</span> <span class="identifier">first</span> <span class="special">=</span> <span class="identifier">functor_multi_pass_t</span><span class="special">(</span><span class="identifier">iterate_a2m</span><span class="special">());</span> |
| <span class="identifier">functor_multi_pass_type</span> <span class="identifier">last</span><span class="special">;</span> |
| |
| <span class="comment">// use the iterators: this will print "ABCDEFGHIJKL" |
| </span><span class="keyword">while</span> <span class="special">(</span><span class="identifier">first</span> <span class="special">!=</span> <span class="identifier">last</span><span class="special">)</span> <span class="special">{</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="special">*</span><span class="identifier">first</span><span class="special">;</span> |
| <span class="special">++</span><span class="identifier">first</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <a name="spirit.support.multi_pass.how_to_write_policies_for_use_with_multi_pass"></a><h5> |
| <a name="id1207474"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.how_to_write_policies_for_use_with_multi_pass">How |
| to write policies for use with multi_pass</a> |
| </h5> |
| <p> |
| All policies to be used with the <code class="computeroutput"><span class="identifier">default_policy</span></code> |
| template need to have two embedded classes: <code class="computeroutput"><span class="identifier">unique</span></code> |
| and <code class="computeroutput"><span class="identifier">shared</span></code>. The <code class="computeroutput"><span class="identifier">unique</span></code> class needs to implement all required |
| functions for a particular policy type. In addition it may hold all member |
| data items being <span class="emphasis"><em>unique</em></span> for a particular instance of |
| a <code class="computeroutput"><span class="identifier">multi_pass</span></code> (hence the name). |
| The <code class="computeroutput"><span class="identifier">shared</span></code> class does not |
| expose any member functions (except sometimes a constructor), but it may |
| hold all member data items to be <span class="emphasis"><em>shared</em></span> between all |
| copies of a particular <code class="computeroutput"><span class="identifier">multi_pass</span></code>. |
| </p> |
| <a name="spirit.support.multi_pass.inputpolicy"></a><h5> |
| <a name="id1207548"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.inputpolicy">InputPolicy</a> |
| </h5> |
| <p> |
| An <code class="computeroutput"><span class="identifier">InputPolicy</span></code> must have |
| the following interface: |
| </p> |
| <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">input_policy</span> |
| <span class="special">{</span> |
| <span class="comment">// Input is the same type used as the first template parameter |
| </span> <span class="comment">// while instantiating the multi_pass |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Input</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">unique</span> |
| <span class="special">{</span> |
| <span class="comment">// these typedef's will be exposed as the multi_pass iterator |
| </span> <span class="comment">// properties |
| </span> <span class="keyword">typedef</span> <span class="identifier">__unspecified_type__</span> <span class="identifier">value_type</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">__unspecified_type__</span> <span class="identifier">difference_type</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">__unspecified_type__</span> <span class="identifier">distance_type</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">__unspecified_type__</span> <span class="identifier">pointer</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">__unspecified_type__</span> <span class="identifier">reference</span><span class="special">;</span> |
| |
| <span class="identifier">unique</span><span class="special">()</span> <span class="special">{}</span> |
| <span class="keyword">explicit</span> <span class="identifier">unique</span><span class="special">(</span><span class="identifier">Input</span><span class="special">)</span> <span class="special">{}</span> |
| |
| <span class="comment">// destroy is called whenever the last copy of a multi_pass is |
| </span> <span class="comment">// destructed (ownership_policy::release() returned true) |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">destroy</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// swap is called by multi_pass::swap() |
| </span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">unique</span><span class="special">&);</span> |
| |
| <span class="comment">// get_input is called whenever the next input character/token |
| </span> <span class="comment">// should be fetched. |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// This method is expected to return a reference to the next |
| </span> <span class="comment">// character/token |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">::</span><span class="identifier">reference</span> <span class="identifier">get_input</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// advance_input is called whenever the underlying input stream |
| </span> <span class="comment">// should be advanced so that the next call to get_input will be |
| </span> <span class="comment">// able to return the next input character/token |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">advance_input</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// input_at_eof is called to test whether this instance is a |
| </span> <span class="comment">// end of input iterator. |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// This method is expected to return true if the end of input is |
| </span> <span class="comment">// reached. It is often used in the implementation of the function |
| </span> <span class="comment">// storage_policy::is_eof. |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">input_at_eof</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// input_is_valid is called to verify if the parameter t represents |
| </span> <span class="comment">// a valid input character/token |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// t: is the character/token to test for validity |
| </span> <span class="comment">// |
| </span> <span class="comment">// This method is expected to return true if the parameter t |
| </span> <span class="comment">// represents a valid character/token. |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">input_is_valid</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">,</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">t</span><span class="special">);</span> |
| <span class="special">};</span> |
| |
| <span class="comment">// Input is the same type used as the first template parameter passed |
| </span> <span class="comment">// while instantiating the multi_pass |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Input</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">shared</span> |
| <span class="special">{</span> |
| <span class="keyword">explicit</span> <span class="identifier">shared</span><span class="special">(</span><span class="identifier">Input</span><span class="special">)</span> <span class="special">{}</span> |
| <span class="special">};</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| It is possible to derive the struct <code class="computeroutput"><span class="identifier">unique</span></code> |
| from the type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">default_input_policy</span></code>. This type implements |
| a minimal sufficient interface for some of the required functions, simplifying |
| the task of writing a new input policy. |
| </p> |
| <p> |
| This class may implement a function <code class="computeroutput"><span class="identifier">destroy</span><span class="special">()</span></code> being called during destruction of the |
| last copy of a <code class="computeroutput"><span class="identifier">multi_pass</span></code>. |
| This function should be used to free any of the shared data items the policy |
| might have allocated during construction of its <code class="computeroutput"><span class="identifier">shared</span></code> |
| part. Because of the way <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| is implemented any allocated data members in <code class="computeroutput"><span class="identifier">shared</span></code> |
| should <span class="underline">not</span> be deep copied in a copy |
| constructor of <code class="computeroutput"><span class="identifier">shared</span></code>. |
| </p> |
| <a name="spirit.support.multi_pass.ownershippolicy"></a><h5> |
| <a name="id1209699"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.ownershippolicy">OwnershipPolicy</a> |
| </h5> |
| <p> |
| The <code class="computeroutput"><span class="identifier">OwnershipPolicy</span></code> must |
| have the following interface: |
| </p> |
| <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">ownership_policy</span> |
| <span class="special">{</span> |
| <span class="keyword">struct</span> <span class="identifier">unique</span> |
| <span class="special">{</span> |
| <span class="comment">// destroy is called whenever the last copy of a multi_pass is |
| </span> <span class="comment">// destructed (ownership_policy::release() returned true) |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">destroy</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// swap is called by multi_pass::swap() |
| </span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">unique</span><span class="special">&);</span> |
| |
| <span class="comment">// clone is called whenever a multi_pass is copied |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">clone</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// release is called whenever a multi_pass is destroyed |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// The method is expected to return true if the destructed |
| </span> <span class="comment">// instance is the last copy of a particular multi_pass. |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">release</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// is_unique is called to test whether this instance is the only |
| </span> <span class="comment">// existing copy of a particular multi_pass |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// The method is expected to return true if this instance is unique |
| </span> <span class="comment">// (no other copies of this multi_pass exist). |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">is_unique</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">struct</span> <span class="identifier">shared</span> <span class="special">{};</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| It is possible to derive the struct <code class="computeroutput"><span class="identifier">unique</span></code> |
| from the type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">default_ownership_policy</span></code>. This type implements |
| a minimal sufficient interface for some of the required functions, simplifying |
| the task of writing a new ownership policy. |
| </p> |
| <p> |
| This class may implement a function <code class="computeroutput"><span class="identifier">destroy</span><span class="special">()</span></code> being called during destruction of the |
| last copy of a <code class="computeroutput"><span class="identifier">multi_pass</span></code>. |
| This function should be used to free any of the shared data items the policy |
| might have allocated during construction of its <code class="computeroutput"><span class="identifier">shared</span></code> |
| part. Because of the way <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| is implemented any allocated data members in <code class="computeroutput"><span class="identifier">shared</span></code> |
| should <span class="underline">not</span> be deep copied in a copy |
| constructor of <code class="computeroutput"><span class="identifier">shared</span></code>. |
| </p> |
| <a name="spirit.support.multi_pass.checkingpolicy"></a><h5> |
| <a name="id1210233"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.checkingpolicy">CheckingPolicy</a> |
| </h5> |
| <p> |
| The <code class="computeroutput"><span class="identifier">CheckingPolicy</span></code> must have |
| the following interface: |
| </p> |
| <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">checking_policy</span> |
| <span class="special">{</span> |
| <span class="keyword">struct</span> <span class="identifier">unique</span> |
| <span class="special">{</span> |
| <span class="comment">// swap is called by multi_pass::swap() |
| </span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">unique</span><span class="special">&);</span> |
| |
| <span class="comment">// destroy is called whenever the last copy of a multi_pass is |
| </span> <span class="comment">// destructed (ownership_policy::release() returned true) |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">destroy</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// docheck is called before the multi_pass is dereferenced or |
| </span> <span class="comment">// incremented. |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// This method is expected to make sure the multi_pass instance is |
| </span> <span class="comment">// still valid. If it is invalid an exception should be thrown. |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">docheck</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// clear_queue is called whenever the function |
| </span> <span class="comment">// multi_pass::clear_queue is called on this instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">clear_queue</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">struct</span> <span class="identifier">shared</span> <span class="special">{};</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| It is possible to derive the struct <code class="computeroutput"><span class="identifier">unique</span></code> |
| from the type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">default_checking_policy</span></code>. This type implements |
| a minimal sufficient interface for some of the required functions, simplifying |
| the task of writing a new checking policy. |
| </p> |
| <p> |
| This class may implement a function <code class="computeroutput"><span class="identifier">destroy</span><span class="special">()</span></code> being called during destruction of the |
| last copy of a <code class="computeroutput"><span class="identifier">multi_pass</span></code>. |
| This function should be used to free any of the shared data items the policy |
| might have allocated during construction of its <code class="computeroutput"><span class="identifier">shared</span></code> |
| part. Because of the way <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| is implemented any allocated data members in <code class="computeroutput"><span class="identifier">shared</span></code> |
| should <span class="underline">not</span> be deep copied in a copy |
| constructor of <code class="computeroutput"><span class="identifier">shared</span></code>. |
| </p> |
| <a name="spirit.support.multi_pass.storagepolicy"></a><h5> |
| <a name="id1210684"></a> |
| <a class="link" href="multi_pass.html#spirit.support.multi_pass.storagepolicy">StoragePolicy</a> |
| </h5> |
| <p> |
| A <code class="computeroutput"><span class="identifier">StoragePolicy</span></code> must have |
| the following interface: |
| </p> |
| <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">storage_policy</span> |
| <span class="special">{</span> |
| <span class="comment">// Value is the same type as typename MultiPass::value_type |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Value</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">unique</span> |
| <span class="special">{</span> |
| <span class="comment">// destroy is called whenever the last copy of a multi_pass is |
| </span> <span class="comment">// destructed (ownership_policy::release() returned true) |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">destroy</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// swap is called by multi_pass::swap() |
| </span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">unique</span><span class="special">&);</span> |
| |
| <span class="comment">// dereference is called whenever multi_pass::operator*() is invoked |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// This function is expected to return a reference to the current |
| </span> <span class="comment">// character/token. |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">::</span><span class="identifier">reference</span> <span class="identifier">dereference</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// increment is called whenever multi_pass::operator++ is invoked |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">increment</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">clear_queue</span><span class="special">(</span><span class="identifier">MultiPass</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// is_eof is called to test whether this instance is a end of input |
| </span> <span class="comment">// iterator. |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// |
| </span> <span class="comment">// This method is expected to return true if the end of input is |
| </span> <span class="comment">// reached. |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">is_eof</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">);</span> |
| |
| <span class="comment">// less_than is called whenever multi_pass::operator==() is invoked |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// rhs: is the multi_pass reference this instance is compared |
| </span> <span class="comment">// to |
| </span> <span class="comment">// |
| </span> <span class="comment">// This function is expected to return true if the current instance |
| </span> <span class="comment">// is equal to the right hand side multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">equal_to</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">,</span> <span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span> |
| |
| <span class="comment">// less_than is called whenever multi_pass::operator<() is invoked |
| </span> <span class="comment">// |
| </span> <span class="comment">// mp: is a reference to the whole multi_pass instance |
| </span> <span class="comment">// rhs: is the multi_pass reference this instance is compared |
| </span> <span class="comment">// to |
| </span> <span class="comment">// |
| </span> <span class="comment">// This function is expected to return true if the current instance |
| </span> <span class="comment">// is less than the right hand side multi_pass instance |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">MultiPass</span><span class="special">></span> |
| <span class="keyword">static</span> <span class="keyword">bool</span> <span class="identifier">less_than</span><span class="special">(</span><span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">mp</span><span class="special">,</span> <span class="identifier">MultiPass</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">);</span> |
| <span class="special">};</span> |
| |
| <span class="comment">// Value is the same type as typename MultiPass::value_type |
| </span> <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Value</span><span class="special">></span> |
| <span class="keyword">struct</span> <span class="identifier">shared</span> <span class="special">{};</span> |
| <span class="special">};</span> |
| </pre> |
| <p> |
| It is possible to derive the struct <code class="computeroutput"><span class="identifier">unique</span></code> |
| from the type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">default_storage_policy</span></code>. This type implements |
| a minimal sufficient interface for some of the required functions, simplifying |
| the task of writing a new storage policy. |
| </p> |
| <p> |
| This class may implement a function <code class="computeroutput"><span class="identifier">destroy</span><span class="special">()</span></code> being called during destruction of the |
| last copy of a <code class="computeroutput"><span class="identifier">multi_pass</span></code>. |
| This function should be used to free any of the shared data items the policy |
| might have allocated during construction of its <code class="computeroutput"><span class="identifier">shared</span></code> |
| part. Because of the way <code class="computeroutput"><span class="identifier">multi_pass</span></code> |
| is implemented any allocated data members in <code class="computeroutput"><span class="identifier">shared</span></code> |
| should <span class="underline">not</span> be deep copied in a copy |
| constructor of <code class="computeroutput"><span class="identifier">shared</span></code>. |
| </p> |
| <p> |
| Generally, a <code class="computeroutput"><span class="identifier">StoragePolicy</span></code> |
| is the trickiest policy to implement. You should study and understand the |
| existing <code class="computeroutput"><span class="identifier">StoragePolicy</span></code> classes |
| before you try and write your own. |
| </p> |
| </div> |
| <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> |
| <td align="left"></td> |
| <td align="right"><div class="copyright-footer">Copyright © 2001-2010 Joel de Guzman, Hartmut Kaiser<p> |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| </div></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="../support.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../support.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../faq.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| </body> |
| </html> |