• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
3  "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
4<!--
5    Copyright 2003, Eric Friedman, Itay Maman.
6
7    Distributed under the Boost Software License, Version 1.0. (See accompanying
8    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9-->
10<section id="variant.intro">
11  <title>Introduction</title>
12
13  <using-namespace name="boost"/>
14
15<section id="variant.abstract">
16  <title>Abstract</title>
17
18<para>The <code>variant</code> class template is a safe, generic, stack-based
19discriminated union container, offering a simple solution for manipulating an
20object from a heterogeneous set of types in a uniform manner. Whereas
21standard containers such as <code>std::vector</code> may be thought of as
22"<emphasis role="bold">multi-value, single type</emphasis>,"
23<code>variant</code> is "<emphasis role="bold">multi-type,
24single value</emphasis>."</para>
25
26<para>Notable features of <code><classname>boost::variant</classname></code>
27include:</para>
28
29<itemizedlist>
30  <listitem>Full value semantics, including adherence to standard
31    overload resolution rules for conversion operations.</listitem>
32  <listitem>Compile-time type-safe value visitation via
33    <code><functionname>boost::apply_visitor</functionname></code>.</listitem>
34  <listitem>Run-time checked explicit value retrieval via
35    <code><functionname>boost::get</functionname></code>.</listitem>
36  <listitem>Support for recursive variant types via both
37    <code><classname>boost::make_recursive_variant</classname></code> and
38    <code><classname>boost::recursive_wrapper</classname></code>.</listitem>
39  <listitem>Efficient implementation -- stack-based when possible (see
40    <xref linkend="variant.design.never-empty"/> for more details).</listitem>
41</itemizedlist>
42
43</section>
44
45<section id="variant.motivation">
46  <title>Motivation</title>
47
48<section id="variant.motivation.problem">
49  <title>Problem</title>
50
51<para>Many times, during the development of a C++ program, the
52programmer finds himself in need of manipulating several distinct
53types in a uniform manner. Indeed, C++ features direct language
54support for such types through its <code>union</code>
55keyword:</para>
56
57<programlisting>union { int i; double d; } u;
58u.d = 3.14;
59u.i = 3; // overwrites u.d (OK: u.d is a POD type)</programlisting>
60
61<para>C++'s <code>union</code> construct, however, is nearly
62useless in an object-oriented environment. The construct entered
63the language primarily as a means for preserving compatibility with
64C, which supports only POD (Plain Old Data) types, and so does not
65accept types exhibiting non-trivial construction or
66destruction:</para>
67
68<programlisting>union {
69  int i;
70  std::string s; // illegal: std::string is not a POD type!
71} u;</programlisting>
72
73<para>Clearly another approach is required. Typical solutions
74feature the dynamic-allocation of objects, which are subsequently
75manipulated through a common base type (often a virtual base class
76    [<link linkend="variant.refs.hen01">Hen01</link>]
77or, more dangerously, a <code>void*</code>). Objects of
78concrete type may be then retrieved by way of a polymorphic downcast
79construct (e.g., <code>dynamic_cast</code>,
80<code><functionname>boost::any_cast</functionname></code>, etc.).</para>
81
82<para>However, solutions of this sort are highly error-prone, due
83to the following:</para>
84
85<itemizedlist>
86  <listitem><emphasis>Downcast errors cannot be detected at
87    compile-time.</emphasis> Thus, incorrect usage of downcast
88    constructs will lead to bugs detectable only at run-time.</listitem>
89  <listitem><emphasis>Addition of new concrete types may be
90    ignored.</emphasis> If a new concrete type is added to the
91    hierarchy, existing downcast code will continue to work as-is,
92    wholly ignoring the new type. Consequently, the programmer must
93    manually locate and modify code at numerous locations, which often
94    results in run-time errors that are difficult to find.</listitem>
95</itemizedlist>
96
97<para>Furthermore, even when properly implemented, these solutions tend
98to incur a relatively significant abstraction penalty due to the use of
99the heap, virtual function calls, and polymorphic downcasts.</para>
100
101</section>
102
103<section id="variant.motivation.solution">
104  <title>Solution: A Motivating Example</title>
105
106<para>The <code><classname>boost::variant</classname></code> class template
107addresses these issues in a safe, straightforward, and efficient manner. The
108following example demonstrates how the class can be used:</para>
109
110<programlisting>#include "boost/variant.hpp"
111#include &lt;iostream&gt;
112
113class my_visitor : public <classname>boost::static_visitor</classname>&lt;int&gt;
114{
115public:
116    int operator()(int i) const
117    {
118        return i;
119    }
120
121    int operator()(const <classname>std::string</classname> &amp; str) const
122    {
123        return str.length();
124    }
125};
126
127int main()
128{
129    <classname>boost::variant</classname>&lt; int, std::string &gt; u("hello world");
130    std::cout &lt;&lt; u; // output: hello world
131
132    int result = <functionname>boost::apply_visitor</functionname>( my_visitor(), u );
133    std::cout &lt;&lt; result; // output: 11 (i.e., length of "hello world")
134}
135</programlisting>
136
137</section>
138
139</section>
140
141</section>
142