...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
Copyright © 2014-2021 Antony Polukhin
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt
or copy at
http://www.boost.org/LICENSE_1_0.txt)
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") }