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