Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/doc/html/variant/tutorial.html @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 31.8 KB
Line 
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
4<title>Tutorial</title>
5<link rel="stylesheet" href="../boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.69.1">
7<link rel="start" href="../index.html" title="The Boost C++ Libraries">
8<link rel="up" href="../variant.html" title="Chapter 15. Boost.Variant">
9<link rel="prev" href="../variant.html" title="Chapter 15. Boost.Variant">
10<link rel="next" href="reference.html" title="Reference">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%">
14<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td>
15<td align="center"><a href="../../../index.htm">Home</a></td>
16<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="../../../people/people.htm">People</a></td>
18<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
19<td align="center"><a href="../../../more/index.htm">More</a></td>
20</table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="../variant.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../variant.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="reference.html"><img src="../images/next.png" alt="Next"></a>
24</div>
25<div class="section" lang="en">
26<div class="titlepage"><div><div><h3 class="title">
27<a name="variant.tutorial"></a>Tutorial</h3></div></div></div>
28<div class="toc"><dl>
29<dt><span class="section"><a href="tutorial.html#variant.tutorial.basic">Basic Usage</a></span></dt>
30<dt><span class="section"><a href="tutorial.html#variant.tutorial.advanced">Advanced Topics</a></span></dt>
31</dl></div>
32<div class="section" lang="en">
33<div class="titlepage"><div><div><h4 class="title">
34<a name="variant.tutorial.basic"></a>Basic Usage</h4></div></div></div>
35<p>A discriminated union container on some set of types is defined by
36  instantiating the <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code> class
37  template with the desired types. These types are called
38  <span class="bold"><strong>bounded types</strong></span> and are subject to the
39  requirements of the
40  <a href="reference.html#variant.concepts.bounded-type" title="BoundedType"><span class="emphasis"><em>BoundedType</em></span></a>
41  concept. Any number of bounded types may be specified, up to some
42  implementation-defined limit (see
43  <code class="computeroutput"><a href="../BOOST_VARIANT_LIMIT_TYPES.html" title="Macro BOOST_VARIANT_LIMIT_TYPES">BOOST_VARIANT_LIMIT_TYPES</a></code>).</p>
44<p>For example, the following declares a discriminated union container on
45  <code class="computeroutput">int</code> and <code class="computeroutput">std::string</code>:
46
47</p>
48<pre class="programlisting"><code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt; int, std::string &gt; v;</pre>
49<p>By default, a <code class="computeroutput">variant</code> default-constructs its first
50  bounded type, so <code class="computeroutput">v</code> initially contains <code class="computeroutput">int(0)</code>. If
51  this is not desired, or if the first bounded type is not
52  default-constructible, a <code class="computeroutput">variant</code> can be constructed
53  directly from any value convertible to one of its bounded types. Similarly,
54  a <code class="computeroutput">variant</code> can be assigned any value convertible to one of its
55  bounded types, as demonstrated in the following:
56
57</p>
58<pre class="programlisting">v = "hello";</pre>
59<p>Now <code class="computeroutput">v</code> contains a <code class="computeroutput">std::string</code> equal to
60  <code class="computeroutput">"hello"</code>. We can demonstrate this by
61  <span class="bold"><strong>streaming</strong></span> <code class="computeroutput">v</code> to standard
62  output:
63
64</p>
65<pre class="programlisting">std::cout &lt;&lt; v &lt;&lt; std::endl;</pre>
66<p>Usually though, we would like to do more with the content of a
67  <code class="computeroutput">variant</code> than streaming. Thus, we need some way to access the
68  contained value. There are two ways to accomplish this:
69  <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">apply_visitor</a></code>, which is safest
70  and very powerful, and
71  <code class="computeroutput"><a href="../get.html" title="Function get">get</a>&lt;T&gt;</code>, which is
72  sometimes more convenient to use.</p>
73<p>For instance, suppose we wanted to concatenate to the string contained
74  in <code class="computeroutput">v</code>. With <span class="bold"><strong>value retrieval</strong></span>
75  by <code class="computeroutput"><a href="../get.html" title="Function get">get</a></code>, this may be accomplished
76  quite simply, as seen in the following:
77
78</p>
79<pre class="programlisting">std::string&amp; str = <code class="computeroutput"><a href="../get.html" title="Function get">boost::get</a></code>&lt;std::string&gt;(v);
80str += " world! ";</pre>
81<p>As desired, the <code class="computeroutput">std::string</code> contained by <code class="computeroutput">v</code> now
82  is equal to <code class="computeroutput">"hello world! "</code>. Again, we can demonstrate this by
83  streaming <code class="computeroutput">v</code> to standard output:
84
85</p>
86<pre class="programlisting">std::cout &lt;&lt; v &lt;&lt; std::endl;</pre>
87<p>While use of <code class="computeroutput">get</code> is perfectly acceptable in this trivial
88  example, <code class="computeroutput">get</code> generally suffers from several significant
89  shortcomings. For instance, if we were to write a function accepting a
90  <code class="computeroutput">variant&lt;int, std::string&gt;</code>, we would not know whether
91  the passed <code class="computeroutput">variant</code> contained an <code class="computeroutput">int</code> or a
92  <code class="computeroutput">std::string</code>. If we insisted upon continued use of
93  <code class="computeroutput">get</code>, we would need to query the <code class="computeroutput">variant</code> for its
94  contained type. The following function, which "doubles" the
95  content of the given <code class="computeroutput">variant</code>, demonstrates this approach:
96
97</p>
98<pre class="programlisting">void times_two( boost::variant&lt; int, std::string &gt; &amp; operand )
99{
100    if ( int* pi = <code class="computeroutput"><a href="../get.html" title="Function get">boost::get</a></code>&lt;int&gt;( &amp;v ) )
101        *pi *= 2;
102    else if ( std::string* pstr = <code class="computeroutput"><a href="../get.html" title="Function get">boost::get</a></code>&lt;std::string&gt;( &amp;v ) )
103        *pstr += *pstr;
104}</pre>
105<p>However, such code is quite brittle, and without careful attention will
106  likely lead to the introduction of subtle logical errors detectable only at
107  runtime. For instance, consider if we wished to extend
108  <code class="computeroutput">times_two</code> to operate on a <code class="computeroutput">variant</code> with additional
109  bounded types. Specifically, let's add
110  <code class="computeroutput">std::complex&lt;double&gt;</code> to the set. Clearly, we would need
111  to at least change the function declaration:
112
113</p>
114<pre class="programlisting">void times_two( boost::variant&lt; int, std::string, std::complex&lt;double&gt; &gt; &amp; operand )
115{
116    // as above...?
117}</pre>
118<p>Of course, additional changes are required, for currently if the passed
119  <code class="computeroutput">variant</code> in fact contained a <code class="computeroutput">std::complex</code> value,
120  <code class="computeroutput">times_two</code> would silently return -- without any of the desired
121  side-effects and without any error. In this case, the fix is obvious. But in
122  more complicated programs, it could take considerable time to identify and
123  locate the error in the first place.</p>
124<p>Thus, real-world use of <code class="computeroutput">variant</code> typically demands an access
125  mechanism more robust than <code class="computeroutput">get</code>. For this reason,
126  <code class="computeroutput">variant</code> supports compile-time checked
127  <span class="bold"><strong>visitation</strong></span> via
128  <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">apply_visitor</a></code>. Visitation requires
129  that the programmer explicitly handle (or ignore) each bounded type. Failure
130  to do so results in a compile-time error.</p>
131<p>Visitation of a <code class="computeroutput">variant</code> requires a visitor object. The
132  following demonstrates one such implementation of a visitor implementating
133  behavior identical to <code class="computeroutput">times_two</code>:
134
135</p>
136<pre class="programlisting">class times_two_visitor
137    : public <code class="computeroutput"><a href="../static_visitor.html" title="Class template static_visitor">boost::static_visitor</a></code>&lt;&gt;
138{
139public:
140
141    void operator()(int &amp; i) const
142    {
143        i *= 2;
144    }
145
146    void operator()(std::string &amp; str) const
147    {
148        str += str;
149    }
150
151};</pre>
152<p>With the implementation of the above visitor, we can then apply it to
153  <code class="computeroutput">v</code>, as seen in the following:
154
155</p>
156<pre class="programlisting"><code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( times_two_visitor(), v );</pre>
157<p>As expected, the content of <code class="computeroutput">v</code> is now a
158  <code class="computeroutput">std::string</code> equal to <code class="computeroutput">"hello world! hello world! "</code>.
159  (We'll skip the verification this time.)</p>
160<p>In addition to enhanced robustness, visitation provides another
161  important advantage over <code class="computeroutput">get</code>: the ability to write generic
162  visitors. For instance, the following visitor will "double" the
163  content of <span class="emphasis"><em>any</em></span> <code class="computeroutput">variant</code> (provided its
164  bounded types each support operator+=):
165
166</p>
167<pre class="programlisting">class times_two_generic
168    : public <code class="computeroutput"><a href="../static_visitor.html" title="Class template static_visitor">boost::static_visitor</a></code>&lt;&gt;
169{
170public:
171
172    template &lt;typename T&gt;
173    void operator()( T &amp; operand ) const
174    {
175        operand += operand;
176    }
177
178};</pre>
179<p>Again, <code class="computeroutput">apply_visitor</code> sets the wheels in motion:
180
181</p>
182<pre class="programlisting"><code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( times_two_generic(), v );</pre>
183<p>While the initial setup costs of visitation may exceed that required for
184  <code class="computeroutput">get</code>, the benefits quickly become significant. Before concluding
185  this section, we should explore one last benefit of visitation with
186  <code class="computeroutput">apply_visitor</code>:
187  <span class="bold"><strong>delayed visitation</strong></span>. Namely, a special form
188  of <code class="computeroutput">apply_visitor</code> is available that does not immediately apply
189  the given visitor to any <code class="computeroutput">variant</code> but rather returns a function
190  object that operates on any <code class="computeroutput">variant</code> given to it. This behavior
191  is particularly useful when operating on sequences of <code class="computeroutput">variant</code>
192  type, as the following demonstrates:
193
194</p>
195<pre class="programlisting">std::vector&lt; <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt;int, std::string&gt; &gt; vec;
196vec.push_back( 21 );
197vec.push_back( "hello " );
198
199times_two_generic visitor;
200std::for_each(
201      vec.begin(), vec.end()
202   , <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>(visitor)
203   );</pre>
204</div>
205<div class="section" lang="en">
206<div class="titlepage"><div><div><h4 class="title">
207<a name="variant.tutorial.advanced"></a>Advanced Topics</h4></div></div></div>
208<div class="toc"><dl>
209<dt><span class="section"><a href="tutorial.html#variant.tutorial.preprocessor">Preprocessor macros</a></span></dt>
210<dt><span class="section"><a href="tutorial.html#variant.tutorial.over-sequence">Using a type sequence to specify bounded types</a></span></dt>
211<dt><span class="section"><a href="tutorial.html#variant.tutorial.recursive">Recursive <code class="computeroutput">variant</code> types</a></span></dt>
212<dt><span class="section"><a href="tutorial.html#variant.tutorial.binary-visitation">Binary visitation</a></span></dt>
213</dl></div>
214<p>This section discusses several features of the library often required
215  for advanced uses of <code class="computeroutput">variant</code>. Unlike in the above section, each
216  feature presented below is largely independent of the others. Accordingly,
217  this section is not necessarily intended to be read linearly or in its
218  entirety.</p>
219<div class="section" lang="en">
220<div class="titlepage"><div><div><h5 class="title">
221<a name="variant.tutorial.preprocessor"></a>Preprocessor macros</h5></div></div></div>
222<p>While the <code class="computeroutput">variant</code> class template's variadic parameter
223    list greatly simplifies use for specific instantiations of the template,
224    it significantly complicates use for generic instantiations. For instance,
225    while it is immediately clear how one might write a function accepting a
226    specific <code class="computeroutput">variant</code> instantiation, say
227    <code class="computeroutput">variant&lt;int, std::string&gt;</code>, it is less clear how one
228    might write a function accepting any given <code class="computeroutput">variant</code>.</p>
229<p>Due to the lack of support for true variadic template parameter lists
230    in the C++98 standard, the preprocessor is needed. While the
231    <a href="../../../libs/preprocessor/index.html" target="_top">Preprocessor</a> library provides a general and
232    powerful solution, the need to repeat
233    <code class="computeroutput"><a href="../BOOST_VARIANT_LIMIT_TYPES.html" title="Macro BOOST_VARIANT_LIMIT_TYPES">BOOST_VARIANT_LIMIT_TYPES</a></code>
234    unnecessarily clutters otherwise simple code. Therefore, for common
235    use-cases, this library provides its own macro
236    <code class="computeroutput"><span class="bold"><strong><a href="../BOOST_VARIANT_ENUM_PARAMS.html" title="Macro BOOST_VARIANT_ENUM_PARAMS">BOOST_VARIANT_ENUM_PARAMS</a></strong></span></code>.</p>
237<p>This macro simplifies for the user the process of declaring
238    <code class="computeroutput">variant</code> types in function templates or explicit partial
239    specializations of class templates, as shown in the following:
240
241</p>
242<pre class="programlisting">// general cases
243template &lt;typename T&gt; void some_func(const T &amp;);
244template &lt;typename T&gt; class some_class;
245
246// function template overload
247template &lt;<code class="computeroutput"><a href="../BOOST_VARIANT_ENUM_PARAMS.html" title="Macro BOOST_VARIANT_ENUM_PARAMS">BOOST_VARIANT_ENUM_PARAMS</a></code>(typename T)&gt;
248void some_func(const <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt;<code class="computeroutput"><a href="../BOOST_VARIANT_ENUM_PARAMS.html" title="Macro BOOST_VARIANT_ENUM_PARAMS">BOOST_VARIANT_ENUM_PARAMS</a></code>(T)&gt; &amp;);
249
250// explicit partial specialization
251template &lt;<code class="computeroutput"><a href="../BOOST_VARIANT_ENUM_PARAMS.html" title="Macro BOOST_VARIANT_ENUM_PARAMS">BOOST_VARIANT_ENUM_PARAMS</a></code>(typename T)&gt;
252class some_class&lt; <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt;<code class="computeroutput"><a href="../BOOST_VARIANT_ENUM_PARAMS.html" title="Macro BOOST_VARIANT_ENUM_PARAMS">BOOST_VARIANT_ENUM_PARAMS</a></code>(T)&gt; &gt;;</pre>
253</div>
254<div class="section" lang="en">
255<div class="titlepage"><div><div><h5 class="title">
256<a name="variant.tutorial.over-sequence"></a>Using a type sequence to specify bounded types</h5></div></div></div>
257<p>While convenient for typical uses, the <code class="computeroutput">variant</code> class
258    template's variadic template parameter list is limiting in two significant
259    dimensions. First, due to the lack of support for true variadic template
260    parameter lists in C++, the number of parameters must be limited to some
261    implementation-defined maximum (namely,
262    <code class="computeroutput"><a href="../BOOST_VARIANT_LIMIT_TYPES.html" title="Macro BOOST_VARIANT_LIMIT_TYPES">BOOST_VARIANT_LIMIT_TYPES</a></code>).
263    Second, the nature of parameter lists in general makes compile-time
264    manipulation of the lists excessively difficult.</p>
265<p>To solve these problems,
266    <code class="computeroutput">make_variant_over&lt; <span class="emphasis"><em>Sequence</em></span> &gt;</code>
267    exposes a <code class="computeroutput">variant</code> whose bounded types are the elements of
268    <code class="computeroutput">Sequence</code> (where <code class="computeroutput">Sequence</code> is any type fulfilling
269    the requirements of <a href="../../../libs/mpl/index.html" target="_top">MPL</a>'s
270    <span class="emphasis"><em>Sequence</em></span> concept). For instance,
271
272</p>
273<pre class="programlisting">typedef <code class="computeroutput">mpl::vector</code>&lt; std::string &gt; types_initial;
274typedef <code class="computeroutput">mpl::push_front</code>&lt; types_initial, int &gt;::type types;
275
276<code class="computeroutput"><a href="../make_variant_over.html" title="Class template make_variant_over">boost::make_variant_over</a></code>&lt; types &gt;::type v1;</pre>
277<p>
278
279    behaves equivalently to
280
281</p>
282<pre class="programlisting"><code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt; int, std::string &gt; v2;</pre>
283<p><span class="bold"><strong>Portability</strong></span>: Unfortunately, due to
284    standard conformance issues in several compilers,
285    <code class="computeroutput">make_variant_over</code> is not universally available. On these
286    compilers the library indicates its lack of support for the syntax via the
287    definition of the preprocessor symbol
288    <code class="computeroutput"><a href="../id2648190.html" title="Macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT">BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT</a></code>.</p>
289</div>
290<div class="section" lang="en">
291<div class="titlepage"><div><div><h5 class="title">
292<a name="variant.tutorial.recursive"></a>Recursive <code class="computeroutput">variant</code> types</h5></div></div></div>
293<div class="toc"><dl>
294<dt><span class="section"><a href="tutorial.html#variant.tutorial.recursive.recursive-wrapper">Recursive types with <code class="computeroutput">recursive_wrapper</code></a></span></dt>
295<dt><span class="section"><a href="tutorial.html#variant.tutorial.recursive.recursive-variant">Recursive types with <code class="computeroutput">make_recursive_variant</code></a></span></dt>
296</dl></div>
297<p>Recursive types facilitate the construction of complex semantics from
298    simple syntax. For instance, nearly every programmer is familiar with the
299    canonical definition of a linked list implementation, whose simple
300    definition allows sequences of unlimited length:
301
302</p>
303<pre class="programlisting">template &lt;typename T&gt;
304struct list_node
305{
306    T data;
307    list_node * next;
308};</pre>
309<p>The nature of <code class="computeroutput">variant</code> as a generic class template
310    unfortunately precludes the straightforward construction of recursive
311    <code class="computeroutput">variant</code> types. Consider the following attempt to construct
312    a structure for simple mathematical expressions:
313
314    </p>
315<pre class="programlisting">struct add;
316struct sub;
317template &lt;typename OpTag&gt; struct binary_op;
318
319typedef <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt;
320      int
321    , binary_op&lt;add&gt;
322    , binary_op&lt;sub&gt;
323    &gt; expression;
324
325template &lt;typename OpTag&gt;
326struct binary_op
327{
328    expression left;  // <span class="emphasis"><em>variant instantiated here...</em></span>
329    expression right;
330
331    binary_op( const expression &amp; lhs, const expression &amp; rhs )
332        : left(lhs), right(rhs)
333    {
334    }
335
336}; // <span class="emphasis"><em>...but binary_op not complete until here!</em></span></pre>
337<p>While well-intentioned, the above approach will not compile because
338    <code class="computeroutput">binary_op</code> is still incomplete when the <code class="computeroutput">variant</code>
339    type <code class="computeroutput">expression</code> is instantiated. Further, the approach suffers
340    from a more significant logical flaw: even if C++ syntax were different
341    such that the above example could be made to "work,"
342    <code class="computeroutput">expression</code> would need to be of infinite size, which is
343    clearly impossible.</p>
344<p>To overcome these difficulties, <code class="computeroutput">variant</code> includes special
345    support for the
346    <code class="computeroutput"><a href="../recursive_wrapper.html" title="Class template recursive_wrapper">boost::recursive_wrapper</a></code> class
347    template, which breaks the circular dependency at the heart of these
348    problems. Further,
349    <code class="computeroutput"><a href="../make_recursive_variant.html" title="Class template make_recursive_variant">boost::make_recursive_variant</a></code> provides
350    a more convenient syntax for declaring recursive <code class="computeroutput">variant</code>
351    types. Tutorials for use of these facilities is described in
352    <a href="tutorial.html#variant.tutorial.recursive.recursive-wrapper" title="Recursive types with recursive_wrapper">the section called &#8220;Recursive types with <code class="computeroutput">recursive_wrapper</code>&#8221;</a> and
353    <a href="tutorial.html#variant.tutorial.recursive.recursive-variant" title="Recursive types with make_recursive_variant">the section called &#8220;Recursive types with <code class="computeroutput">make_recursive_variant</code>&#8221;</a>.</p>
354<div class="section" lang="en">
355<div class="titlepage"><div><div><h6 class="title">
356<a name="variant.tutorial.recursive.recursive-wrapper"></a>Recursive types with <code class="computeroutput">recursive_wrapper</code></h6></div></div></div>
357<p>The following example demonstrates how <code class="computeroutput">recursive_wrapper</code>
358    could be used to solve the problem presented in
359    <a href="tutorial.html#variant.tutorial.recursive" title="Recursive variant types">the section called &#8220;Recursive <code class="computeroutput">variant</code> types&#8221;</a>:
360
361    </p>
362<pre class="programlisting">typedef <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt;
363      int
364    , <code class="computeroutput"><a href="../recursive_wrapper.html" title="Class template recursive_wrapper">boost::recursive_wrapper</a></code>&lt; binary_op&lt;add&gt; &gt;
365    , <code class="computeroutput"><a href="../recursive_wrapper.html" title="Class template recursive_wrapper">boost::recursive_wrapper</a></code>&lt; binary_op&lt;sub&gt; &gt;
366    &gt; expression;</pre>
367<p>Because <code class="computeroutput">variant</code> provides special support for
368    <code class="computeroutput">recursive_wrapper</code>, clients may treat the resultant
369    <code class="computeroutput">variant</code> as though the wrapper were not present. This is seen
370    in the implementation of the following visitor, which calculates the value
371    of an <code class="computeroutput">expression</code> without any reference to
372    <code class="computeroutput">recursive_wrapper</code>:
373
374    </p>
375<pre class="programlisting">class calculator : public <code class="computeroutput"><a href="../static_visitor.html" title="Class template static_visitor">boost::static_visitor&lt;int&gt;</a></code>
376{
377public:
378
379    int operator()(int value) const
380    {
381        return value;
382    }
383
384    int operator()(const binary_op&lt;add&gt; &amp; binary) const
385    {
386        return <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( calculator(), binary.left )
387             + <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( calculator(), binary.right );
388    }
389
390    int operator()(const binary_op&lt;sub&gt; &amp; binary) const
391    {
392        return <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( calculator(), binary.left )
393             - <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( calculator(), binary.right );
394    }
395
396};</pre>
397<p>Finally, we can demonstrate <code class="computeroutput">expression</code> in action:
398 
399    </p>
400<pre class="programlisting">void f()
401{
402    // result = ((7-3)+8) = 12
403    expression result(
404        binary_op&lt;add&gt;(
405            binary_op&lt;sub&gt;(7,3)
406          , 8
407          )
408      );
409
410    assert( <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>(calculator(),result) == 12 );
411}</pre>
412</div>
413<div class="section" lang="en">
414<div class="titlepage"><div><div><h6 class="title">
415<a name="variant.tutorial.recursive.recursive-variant"></a>Recursive types with <code class="computeroutput">make_recursive_variant</code></h6></div></div></div>
416<p>For some applications of recursive <code class="computeroutput">variant</code> types, a user
417    may be able to sacrifice the full flexibility of using
418    <code class="computeroutput">recursive_wrapper</code> with <code class="computeroutput">variant</code> for the following
419    convenient syntax:
420
421</p>
422<pre class="programlisting">typedef <code class="computeroutput"><a href="../make_recursive_variant.html" title="Class template make_recursive_variant">boost::make_recursive_variant</a></code>&lt;
423      int
424    , std::vector&lt; boost::recursive_variant_ &gt;
425    &gt;::type int_tree_t;</pre>
426<p>Use of the resultant <code class="computeroutput">variant</code> type is as expected:
427
428</p>
429<pre class="programlisting">std::vector&lt; int_tree_t &gt; subresult;
430subresult.push_back(3);
431subresult.push_back(5);
432
433std::vector&lt; int_tree_t &gt; result;
434result.push_back(1);
435result.push_back(subresult);
436result.push_back(7);
437
438int_tree_t var(result);</pre>
439<p>To be clear, one might represent the resultant content of
440    <code class="computeroutput">var</code> as <code class="computeroutput">( 1 ( 3 5 ) 7 )</code>.</p>
441<p>Finally, note that a type sequence can be used to specify the bounded
442    types of a recursive <code class="computeroutput">variant</code> via the use of
443    <code class="computeroutput"><a href="../id2655704.html" title="Class template make_recursive_variant_over">boost::make_recursive_variant_over</a></code>,
444    whose semantics are the same as <code class="computeroutput">make_variant_over</code> (which is
445    described in <a href="tutorial.html#variant.tutorial.over-sequence" title="Using a type sequence to specify bounded types">the section called &#8220;Using a type sequence to specify bounded types&#8221;</a>).</p>
446<p><span class="bold"><strong>Portability</strong></span>: Unfortunately, due to
447    standard conformance issues in several compilers,
448    <code class="computeroutput">make_recursive_variant</code> is not universally supported. On these
449    compilers the library indicates its lack of support via the definition
450    of the preprocessor symbol
451    <code class="computeroutput"><a href="../id2404411.html" title="Macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT">BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT</a></code>.
452    Thus, unless working with highly-conformant compilers, maximum portability
453    will be achieved by instead using <code class="computeroutput">recursive_wrapper</code>, as
454    described in
455    <a href="tutorial.html#variant.tutorial.recursive.recursive-wrapper" title="Recursive types with recursive_wrapper">the section called &#8220;Recursive types with <code class="computeroutput">recursive_wrapper</code>&#8221;</a>.</p>
456</div>
457</div>
458<div class="section" lang="en">
459<div class="titlepage"><div><div><h5 class="title">
460<a name="variant.tutorial.binary-visitation"></a>Binary visitation</h5></div></div></div>
461<p>As the tutorial above demonstrates, visitation is a powerful mechanism
462    for manipulating <code class="computeroutput">variant</code> content. Binary visitation further
463    extends the power and flexibility of visitation by allowing simultaneous
464    visitation of the content of two different <code class="computeroutput">variant</code>
465    objects.</p>
466<p>Notably this feature requires that binary visitors are incompatible
467    with the visitor objects discussed in the tutorial above, as they must
468    operate on two arguments. The following demonstrates the implementation of
469    a binary visitor:
470
471</p>
472<pre class="programlisting">class are_strict_equals
473    : public <code class="computeroutput"><a href="../static_visitor.html" title="Class template static_visitor">boost::static_visitor</a></code>&lt;bool&gt;
474{
475public:
476
477    template &lt;typename T, typename U&gt;
478    bool operator()( const T &amp;, const U &amp; ) const
479    {
480        return false; // cannot compare different types
481    }
482
483    template &lt;typename T&gt;
484    bool operator()( const T &amp; lhs, const T &amp; rhs ) const
485    {
486        return lhs == rhs;
487    }
488
489};</pre>
490<p>As expected, the visitor is applied to two <code class="computeroutput">variant</code>
491    arguments by means of <code class="computeroutput">apply_visitor</code>:
492
493</p>
494<pre class="programlisting"><code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt; int, std::string &gt; v1( "hello" );
495
496<code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt; double, std::string &gt; v2( "hello" );
497assert( <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>(are_strict_equals(), v1, v2) );
498
499<code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt; int, const char * &gt; v3( "hello" );
500assert( !<code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>(are_strict_equals(), v1, v3) );</pre>
501<p>Finally, we must note that the function object returned from the
502    "delayed" form of
503    <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">apply_visitor</a></code> also supports
504    binary visitation, as the following demonstrates:
505
506</p>
507<pre class="programlisting">typedef <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">boost::variant</a></code>&lt;double, std::string&gt; my_variant;
508
509std::vector&lt; my_variant &gt; seq1;
510seq1.push_back("pi is close to ");
511seq1.push_back(3.14);
512
513std::list&lt; my_variant &gt; seq2;
514seq2.push_back("pi is close to ");
515seq2.push_back(3.14);
516
517are_strict_equals visitor;
518assert( std::equal(
519      v1.begin(), v1.end(), v2.begin()
520    , <code class="computeroutput"><a href="../apply_visitor.html" title="Function apply_visitor">boost::apply_visitor</a></code>( visitor )
521    ) );</pre>
522</div>
523</div>
524</div>
525<table width="100%"><tr>
526<td align="left"></td>
527<td align="right"><small>Copyright © 2002, 2003 Eric Friedman, Itay Maman</small></td>
528</tr></table>
529<hr>
530<div class="spirit-nav">
531<a accesskey="p" href="../variant.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../variant.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="reference.html"><img src="../images/next.png" alt="Next"></a>
532</div>
533</body>
534</html>
Note: See TracBrowser for help on using the repository browser.