...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Copyright © 2002, 2003 Eric Friedman, Itay Maman
Permission to copy, use, sell and distribute this software is granted provided this copyright notice appears in all copies. Permission to modify the code and to distribute modified code is granted provided this copyright notice appears in all copies, and a notice that the code was modified is included with the copyright notice.
This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.
Table of Contents
The variant
class template is a safe, generic, stack-based
discriminated union container, offering a simple solution for manipulating an
object from a heterogeneous set of types in a uniform manner. Whereas
standard containers such as std::vector
may be thought of as
"multi-value, single type,"
variant
is "multi-type,
single value."
Notable features of boost::variant
include:
boost::apply_visitor
.boost::get
.boost::make_recursive_variant
and
boost::recursive_wrapper
.Many times, during the development of a C++ program, the
programmer finds himself in need of manipulating several distinct
types in a uniform manner. Indeed, C++ features direct language
support for such types through its union
keyword:
union { int i; double d; } u; u.d = 3.14; u.i = 3; // overwrites u.d (OK: u.d is a POD type)
C++'s union
construct, however, is nearly
useless in an object-oriented environment. The construct entered
the language primarily as a means for preserving compatibility with
C, which supports only POD (Plain Old Data) types, and so does not
accept types exhibiting non-trivial construction or
destruction:
union { int i; std::string s; // illegal: std::string is not a POD type! } u;
Clearly another approach is required. Typical solutions
feature the dynamic-allocation of objects, which are subsequently
manipulated through a common base type (often a virtual base class
[Hen01]
or, more dangerously, a void*
). Objects of
concrete type may be then retrieved by way of a polymorphic downcast
construct (e.g., dynamic_cast
,
boost::any_cast
, etc.).
However, solutions of this sort are highly error-prone, due to the following:
Furthermore, even when properly implemented, these solutions tend to incur a relatively significant abstraction penalty due to the use of the heap, virtual function calls, and polymorphic downcasts.
The boost::variant
class template
addresses these issues in a safe, straightforward, and efficient manner. The
following example demonstrates how the class can be used:
#include "boost/variant.hpp" #include <iostream> class my_visitor : publicboost::static_visitor
<int> { public: int operator()(int i) const { return i; } int operator()(conststd::string
& str) const { return str.length(); } }; int main() {boost::variant
< int, std::string > u("hello world"); std::cout << u; // output: hello world int result =boost::apply_visitor
( my_visitor(), u ); std::cout << result; // output: 11 (i.e., length of "hello world") }