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 <iostream> 112 113class my_visitor : public <classname>boost::static_visitor</classname><int> 114{ 115public: 116 int operator()(int i) const 117 { 118 return i; 119 } 120 121 int operator()(const <classname>std::string</classname> & str) const 122 { 123 return str.length(); 124 } 125}; 126 127int main() 128{ 129 <classname>boost::variant</classname>< int, std::string > u("hello world"); 130 std::cout << u; // output: hello world 131 132 int result = <functionname>boost::apply_visitor</functionname>( my_visitor(), u ); 133 std::cout << result; // output: 11 (i.e., length of "hello world") 134} 135</programlisting> 136 137</section> 138 139</section> 140 141</section> 142